python/cpython · error · RuntimeError
no running event loop
Error message
no running event loop
What it means
asyncio.get_running_loop() (and its C equivalent) raises RuntimeError('no running event loop') when called from a thread where no event loop is currently executing. Unlike get_event_loop(), it never falls back to a thread-local loop; it only reports what is actively running right now.
Source
Thrown at Lib/asyncio/events.py:692
# A TLS for the running event loop, used by _get_running_loop.
class _RunningLoop(threading.local):
loop_pid = (None, None)
_running_loop = _RunningLoop()
def get_running_loop():
"""Return the running event loop. Raise a RuntimeError if there is none.
This function is thread-specific.
"""
# NOTE: this function is implemented in C (see _asynciomodule.c)
loop = _get_running_loop()
if loop is None:
raise RuntimeError('no running event loop')
return loop
def _get_running_loop():
"""Return the running event loop or None.
This is a low-level function intended to be used by event loops.
This function is thread-specific.
"""
# NOTE: this function is implemented in C (see _asynciomodule.c)
running_loop, pid = _running_loop.loop_pid
if running_loop is not None and pid == os.getpid():
return running_loop
def _set_running_loop(loop):
"""Set the running event loop.
View on GitHub (pinned to bc6749cc3b)
Solutions
- Call the code from inside a coroutine or callback running under asyncio.run() / loop.run_until_complete()
- Pass the loop explicitly from the caller instead of discovering it
- Use get_event_loop policy or capture the loop while running and reuse it in sync contexts
Example fix
# before
loop = asyncio.get_running_loop() # at module level -> RuntimeError
# after
async def main():
loop = asyncio.get_running_loop() # inside running loop
asyncio.run(main()) Defensive patterns
Strategy: validation
Validate before calling
import asyncio
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None # not inside a running loop; restructure the call site Type guard
def in_running_loop() -> bool:
try:
asyncio.get_running_loop()
return True
except RuntimeError:
return False Try / catch
try:
loop = asyncio.get_running_loop()
except RuntimeError:
raise RuntimeError('call this from inside a coroutine') from None Prevention
- Keep loop-dependent code inside coroutines
- Pass the loop explicitly to sync helpers instead of discovering it
- Capture the loop once while running and store it for later sync use
When it happens
Trigger: Calling get_running_loop() at module import time, in a plain script's top level, inside a threading.Thread, in a synchronous callback invoked by run_in_executor, or after asyncio.run() has finished.
Common situations: Library code that assumes it is inside a coroutine; mixing sync test harnesses with async code; calling async-flavored APIs from synchronous signal handlers or __del__ methods; version upgrade where get_event_loop() deprecation pushed code to get_running_loop().
Related errors
- There is no current event loop in thread %r.
- {htmldir!r} is not a Sphinx HTML output directory
- {name} is not part of stable ABI. Document it as `c:macro::`
- deprecated-removed:: second argument cannot be `next`
- loop must be an instance of AbstractEventLoop or None, not '
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/51b1ef8c2a797922.
Report an issue: GitHub.