Title: [Bug]: Crash when removing colorbar axes in a constrained layout · Issue #31330 · matplotlib/matplotlib · GitHub
Open Graph Title: [Bug]: Crash when removing colorbar axes in a constrained layout · Issue #31330 · matplotlib/matplotlib
X Title: [Bug]: Crash when removing colorbar axes in a constrained layout · Issue #31330 · matplotlib/matplotlib
Description: Bug summary The program crashes if we remove the axes of the colorbar cbar by calling cbar.ax.remove() in a figure with constrained layout. The crash does not occur if we do not specify a constrained layout. Code for reproduction import ...
Open Graph Description: Bug summary The program crashes if we remove the axes of the colorbar cbar by calling cbar.ax.remove() in a figure with constrained layout. The crash does not occur if we do not specify a constrain...
X Description: Bug summary The program crashes if we remove the axes of the colorbar cbar by calling cbar.ax.remove() in a figure with constrained layout. The crash does not occur if we do not specify a constrain...
Opengraph URL: https://github.com/matplotlib/matplotlib/issues/31330
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[Bug]: Crash when removing colorbar axes in a constrained layout","articleBody":"### Bug summary\n\nThe program crashes if we remove the axes of the colorbar `cbar` by calling `cbar.ax.remove()` in a figure with constrained layout. The crash does not occur if we do not specify a constrained layout.\n\n### Code for reproduction\n\n```Python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\ndelta = 0.025\nx = y = np.arange(-3.0, 3.01, delta)\nX, Y = np.meshgrid(x, y)\nZ1 = np.exp(-X**2 - Y**2)\nZ2 = np.exp(-(X - 1)**2 - (Y - 1)**2)\nZ = (Z1 - Z2) * 2\n\nfig, ax = plt.subplots(layout='constrained')\nCS = ax.contourf(X, Y, Z, 10, cmap=\"bone\")\ncbar = fig.colorbar(CS)\ncbar.ax.remove()\nplt.show()\n```\n\n### Actual outcome\n\n---------------------------------------------------------------------------\nAttributeError Traceback (most recent call last)\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/backend_bases.py:1152, in TimerBase._on_timer(self)\n 1146 \"\"\"\n 1147 Runs all function that have been registered as callbacks. Functions\n 1148 can return False (or 0) if they should not be called any more. If there\n 1149 are no callbacks, the timer is automatically stopped.\n 1150 \"\"\"\n 1151 for func, args, kwargs in self.callbacks:\n-\u003e 1152 ret = func(*args, **kwargs)\n 1153 # docstring above explains why we use `if ret == 0` here,\n 1154 # instead of `if not ret`.\n 1155 # This will also catch `ret == False` as `False == 0`\n 1156 # but does not annoy the linters\n 1157 # https://docs.python.org/3/library/stdtypes.html#boolean-values\n 1158 if ret == 0:\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/backends/backend_macosx.py:71, in FigureCanvasMac._single_shot_timer.\u003clocals\u003e.callback_func(callback, timer)\n 70 def callback_func(callback, timer):\n---\u003e 71 callback()\n 72 self._timers.remove(timer)\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/backends/backend_macosx.py:93, in FigureCanvasMac._draw_idle(self)\n 91 return\n 92 self._draw_pending = False\n---\u003e 93 self.draw()\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/backends/backend_macosx.py:56, in FigureCanvasMac.draw(self)\n 54 return\n 55 with cbook._setattr_cm(self, _is_drawing=True):\n---\u003e 56 super().draw()\n 57 self.update()\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:382, in FigureCanvasAgg.draw(self)\n 379 # Acquire a lock on the shared font cache.\n 380 with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar\n 381 else nullcontext()):\n--\u003e 382 self.figure.draw(self.renderer)\n 383 # A GUI class may be need to update a window using this draw, so\n 384 # don't forget to call the superclass.\n 385 super().draw()\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.\u003clocals\u003e.draw_wrapper(artist, renderer, *args, **kwargs)\n 92 @wraps(draw)\n 93 def draw_wrapper(artist, renderer, *args, **kwargs):\n---\u003e 94 result = draw(artist, renderer, *args, **kwargs)\n 95 if renderer._rasterizing:\n 96 renderer.stop_rasterizing()\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.\u003clocals\u003e.draw_wrapper(artist, renderer)\n 68 if artist.get_agg_filter() is not None:\n 69 renderer.start_filter()\n---\u003e 71 return draw(artist, renderer)\n 72 finally:\n 73 if artist.get_agg_filter() is not None:\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/figure.py:3251, in Figure.draw(self, renderer)\n 3249 if self.axes and self.get_layout_engine() is not None:\n 3250 try:\n-\u003e 3251 self.get_layout_engine().execute(self)\n 3252 except ValueError:\n 3253 pass\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/layout_engine.py:278, in ConstrainedLayoutEngine.execute(self, fig)\n 275 w_pad = self._params['w_pad'] / width\n 276 h_pad = self._params['h_pad'] / height\n--\u003e 278 return do_constrained_layout(fig, w_pad=w_pad, h_pad=h_pad,\n 279 wspace=self._params['wspace'],\n 280 hspace=self._params['hspace'],\n 281 rect=self._params['rect'],\n 282 compress=self._compress)\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/_constrained_layout.py:116, in do_constrained_layout(fig, h_pad, w_pad, hspace, wspace, rect, compress)\n 106 return\n 108 for _ in range(2):\n 109 # do the algorithm twice. This has to be done because decorations\n 110 # change size after the first re-position (i.e. x/yticklabels get\n (...)\n 114 # make margins for all the Axes and subfigures in the\n 115 # figure. Add margins for colorbars...\n--\u003e 116 make_layout_margins(layoutgrids, fig, renderer, h_pad=h_pad,\n 117 w_pad=w_pad, hspace=hspace, wspace=wspace)\n 118 make_margin_suptitles(layoutgrids, fig, renderer, h_pad=h_pad,\n 119 w_pad=w_pad)\n 121 # if a layout is such that a columns (or rows) margin has no\n 122 # constraints, we need to make all such instances in the grid\n 123 # match in margin size.\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/_constrained_layout.py:405, in make_layout_margins(layoutgrids, fig, renderer, w_pad, h_pad, hspace, wspace)\n 403 cbp_rspan, cbp_cspan = get_cb_parent_spans(cbax)\n 404 loc = cbax._colorbar_info['location']\n--\u003e 405 cbpos, cbbbox = get_pos_and_bbox(cbax, renderer)\n 406 if loc == 'right':\n 407 if cbp_cspan.stop == ss.colspan.stop:\n 408 # only increase if the colorbar is on the right edge\n\nFile ~/anaconda3/lib/python3.11/site-packages/matplotlib/_constrained_layout.py:644, in get_pos_and_bbox(ax, renderer)\n 642 pos = ax.get_position(original=True)\n 643 # pos is in panel co-ords, but we need in figure for the layout\n--\u003e 644 pos = pos.transformed(fig.transSubfigure - fig.transFigure)\n 645 tightbbox = martist._get_tightbbox_for_layout_only(ax, renderer)\n 646 if tightbbox is None:\n\nAttributeError: 'NoneType' object has no attribute 'transSubfigure'\n\n\n### Expected outcome\n\nA plot without the colorbar is displayed without errors.\n\n### Additional information\n\n_No response_\n\n### Operating system\n\n_No response_\n\n### Matplotlib Version\n\n0.2.0.dev53882+unknown.g607d2c380.g02b42db27\n\n### Matplotlib Backend\n\n_No response_\n\n### Python version\n\n_No response_\n\n### Jupyter version\n\n_No response_\n\n### Installation\n\nNone","author":{"url":"https://github.com/williamlus","@type":"Person","name":"williamlus"},"datePublished":"2026-03-19T04:44:52.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/31330/matplotlib/issues/31330"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:c1693fbb-0f7d-b1e0-7a6b-f2329b9b207b |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 8B18:3CF864:185697E:203A5CA:6A51CD36 |
| html-safe-nonce | 3b8fc75ae96427abe41789f22c9124305d7613ca02357599e58f062805e76f54 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4QjE4OjNDRjg2NDoxODU2OTdFOjIwM0E1Q0E6NkE1MUNEMzYiLCJ2aXNpdG9yX2lkIjoiNjkwNjkyMDQwMDA3NDE2NTU1OCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 094741f2ef680457d19bf0106eb9b7cc7e08b1781d597ab02d8ab6b8c9c3a4df |
| hovercard-subject-tag | issue:4099260039 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/matplotlib/matplotlib/31330/issue_layout |
| twitter:image | https://opengraph.githubassets.com/178615561cc9bf0900a905d2a5aa337ef0122dfeee3996fc1fcdf8cbf12027bf/matplotlib/matplotlib/issues/31330 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/178615561cc9bf0900a905d2a5aa337ef0122dfeee3996fc1fcdf8cbf12027bf/matplotlib/matplotlib/issues/31330 |
| og:image:alt | Bug summary The program crashes if we remove the axes of the colorbar cbar by calling cbar.ax.remove() in a figure with constrained layout. The crash does not occur if we do not specify a constrain... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | williamlus |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| go-import | github.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git |
| octolytics-dimension-user_id | 215947 |
| octolytics-dimension-user_login | matplotlib |
| octolytics-dimension-repository_id | 1385122 |
| octolytics-dimension-repository_nwo | matplotlib/matplotlib |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1385122 |
| octolytics-dimension-repository_network_root_nwo | matplotlib/matplotlib |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7aed05249554b889eb33d002851a973eebcc7e91 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width