Problem
On Python 3.13+, every EventProcessor.stop() logs
Error in event processor queue task during shutdown:
...
asyncio.queues.QueueShutDown
and sends the exception to telemetry, even though shutdown is working as intended.
Mechanism
(packages/reflex-base/src/reflex_base/event/processor/event_processor.py)
The compat shim defines a subclass of the native exception:
if hasattr(asyncio, "QueueShutDown"):
class QueueShutDown(asyncio.QueueShutDown):
...
else:
class QueueShutDown(Exception):
...
Instance checks only work one way: the local class catches itself, but the native asyncio.QueueShutDown raised by queue.get() after stop() calls self._queue.shutdown() is not an instance of the local subclass. As a result:
with contextlib.suppress(QueueShutDown): around the _process_queue loop does not suppress it, so the queue task dies with the native exception, and
- in
stop(), except (asyncio.CancelledError, QueueShutDown, RuntimeError): when awaiting self._queue_task doesn't match either, so the native exception falls through to except Exception, which calls telemetry.send_error(...) and console.error("Error in event processor queue task during shutdown: ...").
Pre-3.13 is unaffected (the queue is never shut down and the local class is only raised, never caught-against-native).
Fix sketch
Alias instead of subclassing when the native exception exists:
if hasattr(asyncio, "QueueShutDown"):
QueueShutDown = asyncio.QueueShutDown
else:
class QueueShutDown(Exception):
...
(or catch asyncio.QueueShutDown explicitly alongside the shim at both sites).
Found while adding drain assertions to the event-loop benchmarks in #6751.
Problem
On Python 3.13+, every
EventProcessor.stop()logsand sends the exception to telemetry, even though shutdown is working as intended.
Mechanism
(
packages/reflex-base/src/reflex_base/event/processor/event_processor.py)The compat shim defines a subclass of the native exception:
Instance checks only work one way: the local class catches itself, but the native
asyncio.QueueShutDownraised byqueue.get()afterstop()callsself._queue.shutdown()is not an instance of the local subclass. As a result:with contextlib.suppress(QueueShutDown):around the_process_queueloop does not suppress it, so the queue task dies with the native exception, andstop(),except (asyncio.CancelledError, QueueShutDown, RuntimeError):when awaitingself._queue_taskdoesn't match either, so the native exception falls through toexcept Exception, which callstelemetry.send_error(...)andconsole.error("Error in event processor queue task during shutdown: ...").Pre-3.13 is unaffected (the queue is never shut down and the local class is only raised, never caught-against-native).
Fix sketch
Alias instead of subclassing when the native exception exists:
(or catch
asyncio.QueueShutDownexplicitly alongside the shim at both sites).Found while adding drain assertions to the event-loop benchmarks in #6751.