Title: [Bug]: Intermittent `ValueError: The passed figure is not managed by pyplot` with ipympl (`%matplotlib widget`) · Issue #622 · matplotlib/ipympl · GitHub
Open Graph Title: [Bug]: Intermittent `ValueError: The passed figure is not managed by pyplot` with ipympl (`%matplotlib widget`) · Issue #622 · matplotlib/ipympl
X Title: [Bug]: Intermittent `ValueError: The passed figure is not managed by pyplot` with ipympl (`%matplotlib widget`) · Issue #622 · matplotlib/ipympl
Description: Bug summary When using Matplotlib with ipympl (%matplotlib widget) in JupyterLab, I intermittently get: ValueError: The passed figure is not managed by pyplot This happens with standard pyplot usage (plt.figure, plt.subplots(num=fig), pl...
Open Graph Description: Bug summary When using Matplotlib with ipympl (%matplotlib widget) in JupyterLab, I intermittently get: ValueError: The passed figure is not managed by pyplot This happens with standard pyplot usag...
X Description: Bug summary When using Matplotlib with ipympl (%matplotlib widget) in JupyterLab, I intermittently get: ValueError: The passed figure is not managed by pyplot This happens with standard pyplot usag...
Opengraph URL: https://github.com/matplotlib/ipympl/issues/622
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[Bug]: Intermittent `ValueError: The passed figure is not managed by pyplot` with ipympl (`%matplotlib widget`)","articleBody":"### Bug summary\n\nWhen using Matplotlib with ipympl (`%matplotlib widget`) in JupyterLab, I intermittently get:\n\n```\nValueError: The passed figure is not managed by pyplot\n```\n\nThis happens with standard pyplot usage (`plt.figure`, `plt.subplots(num=fig)`, `plt.sca(ax)`), without explicitly constructing canvases.\n\n### Code for reproduction\n\n```Python\n%matplotlib widget\nimport time\nimport matplotlib.pyplot as plt\n\ndef try_once():\n fig_num = 1\n plt.close(fig_num)\n fig = plt.figure(fig_num)\n\n fig, axs = plt.subplots(10, 10, num=fig, squeeze=False)\n\n for ax in axs.flat:\n plt.sca(ax) # \u003c-- intermittently raises\n plt.plot([1, 2, 3])\n fig.canvas.draw_idle()\n time.sleep(0.001)\n\nfor i in range(300):\n try:\n try_once()\n except Exception as e:\n print('FAILED at iteration', i, '-\u003e', repr(e))\n raise\n```\n\n### Actual outcome\n\n\n\n```\n---------------------------------------------------------------------------\nValueError Traceback (most recent call last)\nCell In[2], line 20\n 18 for i in range(300):\n 19 try:\n---\u003e 20 try_once()\n 21 except Exception as e:\n 22 print('FAILED at iteration', i, '-\u003e', repr(e))\n\nCell In[2], line 13, in try_once()\n 10 fig, axs = plt.subplots(10, 10, num=fig, squeeze=False)\n 12 for ax in axs.flat:\n---\u003e 13 plt.sca(ax) # \u003c-- intermittently raises\n 14 plt.plot([1, 2, 3])\n 15 fig.canvas.draw_idle()\n\nFile ~/ipympl-debug/issue/.venv/lib/python3.12/site-packages/matplotlib/pyplot.py:1376, in sca(ax)\n 1372 # Mypy sees ax.figure as potentially None,\n 1373 # but if you are calling this, it won't be None\n 1374 # Additionally the slight difference between `Figure` and `FigureBase` mypy catches\n 1375 fig = ax.get_figure(root=False)\n-\u003e 1376 figure(fig) # type: ignore[arg-type]\n 1377 fig.sca(ax)\n\nFile ~/ipympl-debug/issue/.venv/lib/python3.12/site-packages/matplotlib/pyplot.py:995, in figure(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass, clear, **kwargs)\n 993 root_fig = num.get_figure(root=True)\n 994 if root_fig.canvas.manager is None:\n--\u003e 995 raise ValueError(\"The passed figure is not managed by pyplot\")\n 996 elif (any(param is not None for param in [figsize, dpi, facecolor, edgecolor])\n 997 or not frameon or kwargs) and root_fig.canvas.manager.num in allnums:\n 998 _api.warn_external(\n 999 \"Ignoring specified arguments in this call because figure \"\n 1000 f\"with num: {root_fig.canvas.manager.num} already exists\")\n\nValueError: The passed figure is not managed by pyplot\n```\n\n### Expected outcome\n\nMosaicked plots will be shown without errors.\n\n### Additional information\n\n### Observed state at failure\n\nAt the moment the exception occurs:\n- `root_fig.canvas.manager is None`\n- but the corresponding `FigureManager` still exists in `matplotlib._pylab_helpers.Gcf` (so pyplot still manages the figure)\n\nSo pyplot’s “managed figure” check is making a false negative.\n\n### Where the exception comes from\n\n`plt.sca(ax)` calls `pyplot.figure(fig)` internally.\nWhen passed a `Figure`, `pyplot.figure()` currently checks only:\n\n```python\nroot_fig = num.get_figure(root=True)\nif root_fig.canvas.manager is None:\n raise ValueError(\"The passed figure is not managed by pyplot\")\n```\n\nIn this bug, `canvas.manager` is temporarily/incorrectly `None` even though the manager still exists in `Gcf`.\n\n### Proposed fix\n\nIf `root_fig.canvas.manager is None`, fall back to a `Gcf` lookup to find the manager whose `m.canvas.figure is root_fig`, and reattach it.\n\n```python\nmanager = root_fig.canvas.manager\nif manager is None:\n for m in _pylab_helpers.Gcf.get_all_fig_managers():\n if getattr(getattr(m, \"canvas\", None), \"figure\", None) is root_fig:\n manager = m\n root_fig.canvas.manager = m\n break\nif manager is None:\n raise ValueError(...)\n```\n\nThis same logic eliminates the failures in my environment (0/60) when applied as a small monkey patch around `pyplot.figure()`.\n\nThis resembles matplotlib/matplotlib#19380 (same structural cause: `FigureCanvasBase.__init__` sets `self.manager=None` after replacing `figure.canvas`).\n\n### Operating system\n\nUbuntu 24\n\n### Matplotlib Version\n\n3.10.8\n\n### ipympl Version\n\n0.10.0\n\n### Matplotlib Backend\n\nwidget\n\n### Python version\n\nPython 3.12.3\n\n### Jupyter version\n\njupyter lab --version: 4.5.4\n\n### Installation\n\nuv","author":{"url":"https://github.com/michitaro","@type":"Person","name":"michitaro"},"datePublished":"2026-03-02T05:29:45.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":13},"url":"https://github.com/622/ipympl/issues/622"}
| 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:b2348aa7-f524-a344-fa6b-1b4380400adb |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E78C:1A6FEB:13AEE6E:1B0D20D:6A53D451 |
| html-safe-nonce | 95a249cd8ce3ae888e80549f6c76f85f05b6957c4e837ed3d73ccce4f631a5ad |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFNzhDOjFBNkZFQjoxM0FFRTZFOjFCMEQyMEQ6NkE1M0Q0NTEiLCJ2aXNpdG9yX2lkIjoiMzU2MTM4NDY0MTY1NDE1MDIyNSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | e0bb09d61e10a5dad7032545749f07be6f1cca842923c6ce6b9c756bd2f67ddf |
| hovercard-subject-tag | issue:4037614050 |
| 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/ipympl/622/issue_layout |
| twitter:image | https://opengraph.githubassets.com/f7c4634875ac2a300cb08393b046c3c82cc67a8b9e84ca6145f549dbe7bd3608/matplotlib/ipympl/issues/622 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/f7c4634875ac2a300cb08393b046c3c82cc67a8b9e84ca6145f549dbe7bd3608/matplotlib/ipympl/issues/622 |
| og:image:alt | Bug summary When using Matplotlib with ipympl (%matplotlib widget) in JupyterLab, I intermittently get: ValueError: The passed figure is not managed by pyplot This happens with standard pyplot usag... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | michitaro |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| go-import | github.com/matplotlib/ipympl git https://github.com/matplotlib/ipympl.git |
| octolytics-dimension-user_id | 215947 |
| octolytics-dimension-user_login | matplotlib |
| octolytics-dimension-repository_id | 63877123 |
| octolytics-dimension-repository_nwo | matplotlib/ipympl |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 63877123 |
| octolytics-dimension-repository_network_root_nwo | matplotlib/ipympl |
| 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 | 07a982c1d40157c619b364352b704c3ce66bb332 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width