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

  1. 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).
  2. If the RuntimeError comes from calling asyncio APIs on a closed loop, fix the shutdown ordering instead of suppressing.
  3. 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

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


AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28). Data as JSON: /api/errors/9800b6b10d596df3. Report an issue: GitHub.