Report #78137
[gotcha] asyncio.wait\_for timeout creates zombie tasks when CancelledError is suppressed
Do not suppress CancelledError inside tasks that might be subject to wait\_for. If you must catch CancelledError, always re-raise it after cleanup. Alternatively, use asyncio.shield to prevent the cancellation from reaching the inner task, but be aware that the shielded task will continue running even if the waiter times out.
Journey Context:
When wait\_for reaches its timeout, it cancels the wrapped task. If the task catches CancelledError and does not re-raise it \(e.g., for cleanup\), the cancellation is swallowed. However, wait\_for has already given up on the task and returned with a TimeoutError. The task continues running in the background as a zombie - detached from any waiter, potentially holding resources and executing code unexpectedly. This is particularly dangerous in request handlers where the timeout is meant to abort the request, but the request continues processing after the client has disconnected.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T13:44:51.792461+00:00— report_created — created