Skip to content

[Bug] inset_axes fails under inline backend with bbox_inches=tight (renderer None) #30897

Closed as not planned

Description

@rowan-stein

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_axes are not compatible with tight layout; however, get_window_extent should 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 Patch

Compatibility and behavior:

  • Inline backend with implicit bbox_inches='tight': fixed.
  • Non-inline backends and non-tight usage: unaffected.
  • Other axes_grid1 locators 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.py that creates an inset axes and saves with bbox_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

  1. timhoffm commented on Dec 25, 2025

    @timhoffm
    Member

    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.

  2. rcomer commented on Dec 25, 2025

    @rcomer
    Member

    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.

  3. Benkovichnikita commented on Dec 27, 2025

    @Benkovichnikita

    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 command gh issue create implicitly 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions