Repository navigation
Description
User Request
[Bug]: Error while creating inset axes using mpl_toolkits.axes_grid1.inset_locator.inset_axes
Bug summary:
Unable to create the inset axes in a plot using the code (following the first example on the website as posted here).
Code for reproduction:
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
fig, (ax, ax2) = plt.subplots(1, 2, figsize=[5.5, 2.8])
axins = inset_axes(ax, width=1.3, height=0.9)
plt.show()Actual outcome (stack trace excerpt):
AttributeError: 'NoneType' object has no attribute '_get_renderer'
... at matplotlib/offsetbox.py:399 in OffsetBox.get_window_extent
... called from mpl_toolkits/axes_grid1/inset_locator.py:73 in AnchoredLocatorBase.__call__
... triggered via matplotlib/_tight_bbox.py during inline backend bbox_inches='tight'Expected outcome:
An empty box towards the top right of the first subplot (with axes ax), as shown in the demo.
Environment:
- OS: Arch linux: 6.4.2-arch1-1
- Matplotlib Version: 3.7.2
- Backend: module://matplotlib_inline.backend_inline
- Python: 3.8.17
- Jupyter lab: 3.6.5
- Installation: conda
Notes:
- Inline backend applies
bbox="tight"to figure display. - The axes created by
axes_grid1.insetlocator.inset_axesare not compatible with tight layout; however,get_window_extentshould still work.
Task reference: ID 284
Researcher Specification (Emerson Gray)
Overview:
Creating inset axes via mpl_toolkits.axes_grid1.inset_locator.inset_axes fails under IPython inline backend when bbox="tight" is applied implicitly. The failure occurs because AnchoredLocatorBase.__call__ forwards renderer=None to OffsetBox.get_window_extent, which then tries to use self.figure._get_renderer(). Since the locator object is not attached to a figure (self.figure is None), this raises AttributeError.
Minimal fix: Ensure AnchoredLocatorBase.__call__ obtains a valid renderer from the parent Axes’ figure when the passed renderer is None.
Files and exact change:
- Target file:
lib/mpl_toolkits/axes_grid1/inset_locator.py
Patch diff chunk:
*** Begin Patch
*** Update File: lib/mpl_toolkits/axes_grid1/inset_locator.py
@@
class AnchoredLocatorBase(AnchoredOffsetbox):
@@
def draw(self, renderer):
raise RuntimeError("No draw method should be called")
def __call__(self, ax, renderer):
+ # Some callers (e.g., tight bbox adjustment or inset axes setup)
+ # invoke locators with renderer=None. OffsetBox.get_window_extent
+ # will fallback to self.figure._get_renderer() if renderer is None,
+ # but this locator is not attached to a Figure (self.figure is None).
+ # Ensure a valid renderer is used.
+ if renderer is None:
+ renderer = ax.figure._get_renderer()
self.axes = ax
bbox = self.get_window_extent(renderer)
px, py = self.get_offset(bbox.width, bbox.height, 0, 0, renderer)
bbox_canvas = Bbox.from_bounds(px, py, bbox.width, bbox.height)
tr = ax.figure.transSubfigure.inverted()
return TransformedBbox(bbox_canvas, tr)
*** End PatchCompatibility and behavior:
- Inline backend with implicit
bbox_inches='tight': fixed. - Non-inline backends and non-tight usage: unaffected.
- Other
axes_grid1locators benefit similarly. - We do not attach the locator to the figure; passing a valid renderer is sufficient.
Testing plan:
- Manual repro (pre-fix failure, post-fix success):
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
fig, (ax, ax2) = plt.subplots(1, 2, figsize=(5.5, 2.8))
axins = inset_axes(ax, width=1.3, height=0.9)
fig.savefig('out.png', bbox_inches='tight')- Unit test proposal: Add a smoketest to
lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.pythat creates an inset axes and saves withbbox_inches='tight'to ensure no exception.
Edge cases:
tight_layout: existing warnings unchanged; fix prevents error.constrained_layout: unaffected; the renderer derivation is safe.
Reason:
Prevent OffsetBox.get_window_extent from using self.figure when the locator is not attached to a figure, avoiding AttributeError during inline backend tight bbox processing.
Activity
timhoffm commentedon Dec 25, 2025
Spammy repost of #26287.
@rowan-stein this is this he second time you (or your agents) opened an invalid spammy issue. Please make sure this doesn’t happen again.
rcomer commentedon Dec 25, 2025
I guess these were intended for https://github.com/agyn-sandbox/matplotlib. Looks like our old issues are being used to train/test AI bots.
Benkovichnikita commentedon Dec 27, 2025
Hi @rcomer @timhoffm !
We are working on SWE-bench Verified, where AI agents fully automatically solve historical verified issues on forked repositories. During one of these automated runs, an issue was opened here unintentionally.
The root cause was a non-obvious default behavior of the GitHub CLI (gh): even though the repository was cloned from our fork using
gh repo clone, the commandgh issue createimplicitly targeted the upstream repository instead of the fork. This resulted in the issue being created here by automation, not manual action or spam.Apologies again for the inconvenience, and thank you for your understanding.