{"record":{"id":"51b1ef8c2a797922","repo":"python/cpython","slug":"no-running-event-loop","errorCode":null,"errorMessage":"no running event loop","messagePattern":"no running event loop","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Lib/asyncio/events.py","lineNumber":692,"sourceCode":"\n\n# A TLS for the running event loop, used by _get_running_loop.\nclass _RunningLoop(threading.local):\n    loop_pid = (None, None)\n\n\n_running_loop = _RunningLoop()\n\n\ndef get_running_loop():\n    \"\"\"Return the running event loop.  Raise a RuntimeError if there is none.\n\n    This function is thread-specific.\n    \"\"\"\n    # NOTE: this function is implemented in C (see _asynciomodule.c)\n    loop = _get_running_loop()\n    if loop is None:\n        raise RuntimeError('no running event loop')\n    return loop\n\n\ndef _get_running_loop():\n    \"\"\"Return the running event loop or None.\n\n    This is a low-level function intended to be used by event loops.\n    This function is thread-specific.\n    \"\"\"\n    # NOTE: this function is implemented in C (see _asynciomodule.c)\n    running_loop, pid = _running_loop.loop_pid\n    if running_loop is not None and pid == os.getpid():\n        return running_loop\n\n\ndef _set_running_loop(loop):\n    \"\"\"Set the running event loop.\n","sourceCodeStart":674,"sourceCodeEnd":710,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/asyncio/events.py#L674-L710","documentation":"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.","triggerScenarios":"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.","commonSituations":"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().","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"],"exampleFix":"# before\nloop = asyncio.get_running_loop()  # at module level -> RuntimeError\n\n# after\nasync def main():\n    loop = asyncio.get_running_loop()  # inside running loop\nasyncio.run(main())","handlingStrategy":"validation","validationCode":"import asyncio\ntry:\n    loop = asyncio.get_running_loop()\nexcept RuntimeError:\n    loop = None  # not inside a running loop; restructure the call site","typeGuard":"def in_running_loop() -> bool:\n    try:\n        asyncio.get_running_loop()\n        return True\n    except RuntimeError:\n        return False","tryCatchPattern":"try:\n    loop = asyncio.get_running_loop()\nexcept RuntimeError:\n    raise RuntimeError('call this from inside a coroutine') from None","preventionTips":["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"],"tags":["asyncio","event-loop","threading"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}