Report #103743
[bug\_fix] RuntimeError: Event loop is closed when calling asyncio.run\(\) more than once or in a thread
Call \`asyncio.run\(coro\(\)\)\` exactly once as the entry point of the program. Do not call it inside a library, inside another event loop, or multiple times in the same thread. In notebooks or REPLs that already run a loop, use \`await coro\(\)\` directly instead of \`asyncio.run\(\)\`.
Journey Context:
You write an async helper and test it with \`asyncio.run\(main\(\)\)\`. Later you wrap that helper in a synchronous function and call \`asyncio.run\(helper\(\)\)\` from inside a web framework that is already async. The program crashes with Event loop is closed or Cannot run terminal event loop. You try creating new loops with \`asyncio.new\_event\_loop\(\)\` and manually closing them, which works intermittently but leaks in threads. The root cause is that \`asyncio.run\(\)\` creates a new loop, sets it as the thread's current loop, runs the coroutine, and then closes the loop. Calling it again in the same thread finds the closed loop. The established fix is to treat \`asyncio.run\(\)\` as the single top-level entry point and use \`await\` everywhere else, because only one loop should own a thread and cleanup should happen once at program exit.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-13T04:37:42.583685+00:00— report_created — created