Report #75684
[bug\_fix] RuntimeError: There is no current event loop in thread 'MainThread'
Replace \`asyncio.get\_event\_loop\(\)\` with \`asyncio.get\_running\_loop\(\)\` inside coroutines, or \`asyncio.run\(\)\` for entry points. In new threads, explicitly create a loop with \`asyncio.new\_event\_loop\(\)\` and \`asyncio.set\_event\_loop\(\)\`. Root cause: Python 3.10\+ deprecated implicit loop creation in \`get\_event\_loop\(\)\` when no loop is running. In multi-threaded contexts \(e.g., Gunicorn workers, Jupyter\), threads other than main lack a default loop.
Journey Context:
You write a FastAPI endpoint that calls an async helper using \`asyncio.get\_event\_loop\(\).run\_in\_executor\(...\)\`. It works locally with \`uvicorn main:app\`. You deploy to production with Gunicorn using Uvicorn workers, and every request crashes with \`RuntimeError: There is no current event loop in thread 'MainThread'\`. You try wrapping the call in \`asyncio.run\(\)\`, but that fails because you cannot nest \`run\(\)\` inside an already running async context \(FastAPI's request handler is async\). You check the Python version \(3.11\) and realize \`get\_event\_loop\(\)\` behavior changed: it no longer implicitly creates a loop if one isn't running. In Gunicorn workers, the worker process may import modules in a way that triggers this before the loop is set as the default for that thread. The fix is to use \`asyncio.get\_running\_loop\(\)\` inside the async function \(which gets the currently running loop from the context\) instead of \`get\_event\_loop\(\)\`, or if you must create a loop in a new thread \(e.g., for a background worker\), explicitly call \`asyncio.new\_event\_loop\(\)\` and \`asyncio.set\_event\_loop\(loop\)\` before running any async code.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T09:37:40.674991+00:00— report_created — created