python/cpython · error · RuntimeError
There is no current event loop in thread %r.
Error message
There is no current event loop in thread %r.
What it means
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.
Source
Thrown at Lib/asyncio/events.py:727
"""Set the running event loop.
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.loop_pid = (loop, os.getpid())
def _get_event_loop():
"""Return the event loop set for the current thread.
Raise a RuntimeError if no event loop has been set for the current
thread. This is the slow path of get_event_loop(); the running loop
is checked by the caller.
"""
loop = _local._loop
if loop is None:
raise RuntimeError('There is no current event loop in thread %r.'
% threading.current_thread().name)
return loop
def get_event_loop():
"""Return an asyncio event loop.
When called from a coroutine or a callback (e.g. scheduled with call_soon
or similar API), this function will always return the running event loop.
If there is no running event loop set, the function will return
the loop set by ``set_event_loop()``, or raise a RuntimeError if
no loop has been set.
"""
# NOTE: this function is implemented in C (see _asynciomodule.c)
current_loop = _get_running_loop()
if current_loop is not None:
return current_loopView on GitHub (pinned to bc6749cc3b)
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)
Example fix
# before
loop = asyncio.get_event_loop() # RuntimeError in thread
# after
def worker():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(coro)
finally:
loop.close() Defensive patterns
Strategy: validation
Validate before calling
import asyncio
try:
loop = asyncio.get_event_loop()
if loop.is_closed():
loop = None
except RuntimeError:
loop = None # none set for this thread Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- no running event loop
- {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/c54a517846d64f80.
Report an issue: GitHub.