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

  1. Call the code from inside a coroutine or callback running under asyncio.run() / loop.run_until_complete()
  2. Pass the loop explicitly from the caller instead of discovering it
  3. 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

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


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/51b1ef8c2a797922. Report an issue: GitHub.