Report #45645
[bug\_fix] RuntimeError: Task attached to a different loop or Event loop is closed in async code
Never create tasks at module import time \(top-level\) using \`asyncio.create\_task\(\)\`; instead, create them inside \`async def main\(\)\` or use lazy initialization within functions. For Jupyter notebooks, use \`await\` directly if already in an async context, or create a new loop with \`asyncio.new\_event\_loop\(\)\` if the previous one was closed by \`asyncio.run\(\)\`.
Journey Context:
A developer writes an async application and creates a background task at the module level: \`background\_task = asyncio.create\_task\(poll\_queue\(\)\)\`. When running with \`asyncio.run\(main\(\)\)\`, the first execution works. However, in a Jupyter notebook, running the cell twice raises \`RuntimeError: Event loop is closed\` because \`asyncio.run\` closes the loop at the end, and Jupyter's kernel cannot restart it easily. Alternatively, when using \`pytest-asyncio\`, the developer sees \`RuntimeError: Task attached to a different loop\`. This occurs because the task was created during import time when the default event loop was instance A, but the test runs in event loop instance B \(created by the test fixture\). Since \`asyncio\` tasks are bound to the loop that created them, they cannot be awaited or cancelled from a different loop.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T07:05:29.581177+00:00— report_created — created