{"record":{"id":"9800b6b10d596df3","repo":"reflex-dev/reflex","slug":"cannot-suppress-runtimeerror-exceptions-which-may","errorCode":null,"errorMessage":"Cannot suppress RuntimeError exceptions which may be raised by asyncio machinery.","messagePattern":"Cannot suppress RuntimeError exceptions which may be raised by asyncio machinery\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"reflex/utils/tasks.py","lineNumber":95,"sourceCode":"        owner: The owner of the task.\n        task_attribute: The attribute name to store/retrieve the task from the owner object.\n        coro_function: The coroutine function to run as a task.\n        suppress_exceptions: The exceptions to log and continue when running the coroutine.\n        exception_delay: The delay between retries when an exception is suppressed.\n        exception_limit: The maximum number of suppressed exceptions within the limit window before raising.\n        exception_limit_window: The time window in seconds for counting suppressed exceptions.\n        task_context: The context to use for the task.\n        *args: The arguments to pass to the coroutine function.\n        **kwargs: The keyword arguments to pass to the coroutine function.\n\n    Returns:\n        The asyncio task running the coroutine function.\n    \"\"\"\n    if suppress_exceptions is None:\n        suppress_exceptions = []\n    if RuntimeError in suppress_exceptions:\n        msg = \"Cannot suppress RuntimeError exceptions which may be raised by asyncio machinery.\"\n        raise RuntimeError(msg)\n\n    task = getattr(owner, task_attribute, None)\n    if task is None or task.done():\n        asyncio.get_running_loop()  # Ensure we're in an event loop.\n        rf_coro = _run_forever(\n            coro_function,\n            *args,\n            suppress_exceptions=suppress_exceptions,\n            exception_delay=exception_delay,\n            exception_limit=exception_limit,\n            exception_limit_window=exception_limit_window,\n            **kwargs,\n        )\n        task_name = f\"reflex_ensure_task|{type(owner).__name__}.{task_attribute}={coro_function.__name__}|{time.time()}\"\n        if task_context is not None:\n            # Run the task in the given context (not needed after Python 3.11+ which supports passing context to create_task directly).\n            task = task_context.run(asyncio.create_task, rf_coro, name=task_name)\n        else:","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/reflex/utils/tasks.py#L77-L113","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)."],"exampleFix":"# before\nensure_task(poll, self, \"_poll_task\", suppress_exceptions=[RuntimeError, ValueError])\n\n# after\nensure_task(poll, self, \"_poll_task\", suppress_exceptions=[ValueError])","handlingStrategy":"validation","validationCode":"def safe_suppress(excs: list[type[BaseException]]) -> list[type[BaseException]]:\n    if RuntimeError in excs:\n        raise ValueError(\"Reflex forbids suppressing RuntimeError in ensure_task\")\n    return excs","typeGuard":null,"tryCatchPattern":"try:\n    ensure_task(coro, owner, attr, suppress_exceptions=[ConnectionError])\nexcept RuntimeError as e:\n    if \"Cannot suppress RuntimeError\" in str(e):\n        # remove RuntimeError from list and retry without it\n        ...","preventionTips":["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."],"tags":["reflex","asyncio","task-suppression","runtimeerror","background-task"],"backgroundTag":"asyncio-task-exception-suppression","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}