Report #62405
[bug\_fix] RuntimeError: Event loop is closed \(in Jupyter/IPython or pytest-asyncio\)
The root cause is that 'asyncio.run\(\)' creates a new event loop, runs the coroutine, and then \*\*closes the loop permanently\*\*. In interactive environments like Jupyter, IPython, or pytest-asyncio, an event loop is already running in the background to manage the kernel. Calling 'asyncio.run\(\)' once closes that shared loop, causing 'RuntimeError: Event loop is closed' on subsequent async operations. The fix is to avoid 'asyncio.run\(\)' in Jupyter/IPython; instead, 'await' the coroutine directly in a cell \(e.g., 'await main\(\)'\), which uses the existing running loop. For scripts, ensure 'asyncio.run\(\)' is called only once at the entry point.
Journey Context:
Developer is prototyping an async API client in Jupyter Notebook. They write 'asyncio.run\(fetch\_data\(\)\)' in a cell and it works perfectly. They modify the code and run the cell again, getting 'RuntimeError: Event loop is closed'. They restart the kernel and it works once, then fails again. They search and find advice to use 'asyncio.get\_event\_loop\(\).run\_until\_complete\(\)'. They try that and get 'DeprecationWarning' or 'RuntimeError: This event loop is already running'. The rabbit hole reveals that Jupyter already has an event loop running in the background thread \(via tornado/IPython\). When 'asyncio.run\(\)' is called, it calls 'loop.close\(\)' at the end, destroying the kernel's loop. The solution is to simply 'await fetch\_data\(\)' directly in the notebook cell, leveraging the existing loop via 'IPython's async integration.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T11:14:03.059131+00:00— report_created — created