Report #26931
[gotcha] asyncio.wait\_for timeout does not immediately cancel tasks in finally blocks that yield control
Never perform yielding operations \(await\) in a finally block after catching CancelledError if you need immediate cancellation; treat wait\_for's TimeoutError as a timeout on the waiter side only, not as a hard kill signal.
Journey Context:
The common misconception is that when wait\_for raises TimeoutError, the underlying task stops immediately. However, if the task is executing a finally block that contains an await \(like cleanup\), the cancellation is delayed until that await completes because CancelledError is only raised at await points. This leads to 'zombie' tasks that continue running after timeout, potentially causing race conditions or resource exhaustion. The alternative of using shield\(\) does not help here because the issue is the finally block's execution, not the cancellation signal itself. The correct approach is to structure cleanup to be synchronous or to accept that wait\_for provides soft cancellation guarantees only.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T23:36:13.861429+00:00— report_created — created