reflex-dev/reflex · error · RuntimeError
Cannot suppress RuntimeError exceptions which may be raised
Error message
Cannot suppress RuntimeError exceptions which may be raised by asyncio machinery.
What it means
Raised by `reflex.utils.tasks.ensure_task` when the caller passes RuntimeError in `suppress_exceptions`. asyncio machinery itself uses RuntimeError to signal loop-closed or no-running-loop conditions, so suppressing it would mask lifecycle bugs and can hang the owner forever. The guard rejects this explicitly before creating the background task.
Source
Thrown at reflex/utils/tasks.py:95
owner: The owner of the task.
task_attribute: The attribute name to store/retrieve the task from the owner object.
coro_function: The coroutine function to run as a task.
suppress_exceptions: The exceptions to log and continue when running the coroutine.
exception_delay: The delay between retries when an exception is suppressed.
exception_limit: The maximum number of suppressed exceptions within the limit window before raising.
exception_limit_window: The time window in seconds for counting suppressed exceptions.
task_context: The context to use for the task.
*args: The arguments to pass to the coroutine function.
**kwargs: The keyword arguments to pass to the coroutine function.
Returns:
The asyncio task running the coroutine function.
"""
if suppress_exceptions is None:
suppress_exceptions = []
if RuntimeError in suppress_exceptions:
msg = "Cannot suppress RuntimeError exceptions which may be raised by asyncio machinery."
raise RuntimeError(msg)
task = getattr(owner, task_attribute, None)
if task is None or task.done():
asyncio.get_running_loop() # Ensure we're in an event loop.
rf_coro = _run_forever(
coro_function,
*args,
suppress_exceptions=suppress_exceptions,
exception_delay=exception_delay,
exception_limit=exception_limit,
exception_limit_window=exception_limit_window,
**kwargs,
)
task_name = f"reflex_ensure_task|{type(owner).__name__}.{task_attribute}={coro_function.__name__}|{time.time()}"
if task_context is not None:
# Run the task in the given context (not needed after Python 3.11+ which supports passing context to create_task directly).
task = task_context.run(asyncio.create_task, rf_coro, name=task_name)
else:View on GitHub (pinned to 45b8ed5ab7)
Solutions
- Remove RuntimeError from the suppress_exceptions list and handle it explicitly (e.g. let the task die or catch it inside the coroutine and log/restart).
- If the RuntimeError comes from calling asyncio APIs on a closed loop, fix the shutdown ordering instead of suppressing.
- Suppress only the specific exception types your task can safely ignore (e.g. ConnectionError, TimeoutError).
Example fix
# before ensure_task(poll, self, "_poll_task", suppress_exceptions=[RuntimeError, ValueError]) # after ensure_task(poll, self, "_poll_task", suppress_exceptions=[ValueError])
Defensive patterns
Strategy: validation
Validate before calling
def safe_suppress(excs: list[type[BaseException]]) -> list[type[BaseException]]:
if RuntimeError in excs:
raise ValueError("Reflex forbids suppressing RuntimeError in ensure_task")
return excs Try / catch
try:
ensure_task(coro, owner, attr, suppress_exceptions=[ConnectionError])
except RuntimeError as e:
if "Cannot suppress RuntimeError" in str(e):
# remove RuntimeError from list and retry without it
... Prevention
- Never blanket-suppress Exception; list only the specific exceptions your coroutine can safely ignore.
- Handle loop-shutdown RuntimeErrors inside the coroutine with proper cancellation handling.
When it happens
Trigger: Calling `ensure_task(coro, owner, task_attribute, suppress_exceptions=[RuntimeError, ...])` (or with a tuple containing RuntimeError) in any code that starts long-running Reflex background tasks (e.g. _ensure_lock_task, _ensure_socket_record_task, ensure_lost_and_found_task).
Common situations: A user-written background task raises RuntimeError and the developer blanket-suppresses Exception (RuntimeError included) to stop log spam; upgrading Reflex where the suppression API is now validated.
Related errors
- @rx.event(background=True) is required for upload_files_chun
- The state is already mutable. Do not nest `async with self`
- Background task must use `async with self` to modify state.
- Background task StateProxy is immutable outside of a context
- ChildrenTypeError(component=cls.__name__, child=child)
AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28).
Data as JSON: /api/errors/9800b6b10d596df3.
Report an issue: GitHub.