{"record":{"id":"c54a517846d64f80","repo":"python/cpython","slug":"there-is-no-current-event-loop-in-thread-r","errorCode":null,"errorMessage":"There is no current event loop in thread %r.","messagePattern":"There is no current event loop in thread %r\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Lib/asyncio/events.py","lineNumber":727,"sourceCode":"    \"\"\"Set the running event loop.\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.loop_pid = (loop, os.getpid())\n\n\ndef _get_event_loop():\n    \"\"\"Return the event loop set for the current thread.\n\n    Raise a RuntimeError if no event loop has been set for the current\n    thread.  This is the slow path of get_event_loop(); the running loop\n    is checked by the caller.\n    \"\"\"\n    loop = _local._loop\n    if loop is None:\n        raise RuntimeError('There is no current event loop in thread %r.'\n                            % threading.current_thread().name)\n    return loop\n\n\ndef get_event_loop():\n    \"\"\"Return an asyncio event loop.\n\n    When called from a coroutine or a callback (e.g. scheduled with call_soon\n    or similar API), this function will always return the running event loop.\n\n    If there is no running event loop set, the function will return\n    the loop set by ``set_event_loop()``, or raise a RuntimeError if\n    no loop has been set.\n    \"\"\"\n    # NOTE: this function is implemented in C (see _asynciomodule.c)\n    current_loop = _get_running_loop()\n    if current_loop is not None:\n        return current_loop","sourceCodeStart":709,"sourceCodeEnd":745,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/asyncio/events.py#L709-L745","documentation":"Raised by the slow path of asyncio.get_event_loop() when no event loop was ever set for the current thread and none is running. Since Python 3.10+, get_event_loop no longer auto-creates a loop in the main thread, so this RuntimeError is the standard failure for legacy sync-style calls.","triggerScenarios":"Calling asyncio.get_event_loop() in a worker threading.Thread, in a pytest fixture without asyncio mode, or from any sync context after set_event_loop(None)/loop.close() without setting a new one.","commonSituations":"Upgrading to Python 3.10/3.12 where implicit loop creation was removed; background threads doing get_event_loop().run_until_complete(); Jupyter users mixing asyncio APIs; tests that closed the loop in a prior test.","solutions":["Restructure around asyncio.run(main()) instead of get_event_loop()","In a thread: loop = asyncio.new_event_loop(); asyncio.set_event_loop(loop)","Pass the loop from the creating thread explicitly via run_coroutine_threadsafe(coro, loop)"],"exampleFix":"# before\nloop = asyncio.get_event_loop()  # RuntimeError in thread\n\n# after\ndef worker():\n    loop = asyncio.new_event_loop()\n    asyncio.set_event_loop(loop)\n    try:\n        return loop.run_until_complete(coro)\n    finally:\n        loop.close()","handlingStrategy":"validation","validationCode":"import asyncio\ntry:\n    loop = asyncio.get_event_loop()\n    if loop.is_closed():\n        loop = None\nexcept RuntimeError:\n    loop = None  # none set for this thread","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer asyncio.run() over get_event_loop() in scripts","Create and set a fresh loop in worker threads: new_event_loop + set_event_loop","Use run_coroutine_threadsafe when crossing from threads to a loop"],"tags":["asyncio","event-loop","threading","python-3-10"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}