Report #104702
[bug\_fix] \`RuntimeError: Event loop is closed\` in asyncio-based applications when using \`asyncio.run\(\)\` inside a Jupyter notebook or pytest asyncio fixture without proper loop lifecycle management
Do not use \`asyncio.run\(\)\` inside Jupyter or pytest-asyncio contexts. Instead, for Jupyter: use \`await\` directly in a cell. For pytest: decorate test with \`@pytest.mark.asyncio\` and use \`await\` in test functions. If you must use \`asyncio.run\(\)\`, restart the kernel or create a new event loop via \`asyncio.new\_event\_loop\(\)\`.
Journey Context:
A developer was prototyping an async HTTP client in a Jupyter notebook. They defined a function that called \`asyncio.run\(fetch\_data\(\)\)\`. The first invocation worked fine, but the second invocation raised \`RuntimeError: Event loop is closed\`. The developer closed and reopened the notebook cell, ran \`%reset\`, even restarted the kernel manually—only to get the same error again. After researching, they learned that Jupyter's IPython kernel already has a running event loop \(it runs Tornado\), and \`asyncio.run\(\)\` tries to create a new loop, which fails because the existing loop is closed after the first \`run\(\)\`. The official fix is to simply use \`await\` in a Jupyter cell \(which works because IPython 7\+ supports top-level await\). For pytest, the same issue occurs with \`pytest-asyncio\` if you manually call \`asyncio.run\(\)\` inside a fixture—pytest manages the loop lifecycle. The developer switched to \`await fetch\_data\(\)\` in the notebook cell and the error vanished.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-09-27T20:11:44.436672+00:00— report_created — created