Report #17643
[gotcha] asyncio.shield failing to protect coroutine from cancellation due to yield point timing
Apply shield at the outermost level of the operation that must complete, ensuring no suspension points \(await\) exist between starting work and establishing the shield. Structure critical sections as \`task = asyncio.create\_task\(coro\); await asyncio.shield\(task\)\`.
Journey Context:
shield\(\) works by wrapping the awaitable in a new independent task. However, if the coroutine passed to shield contains an inner await point \(e.g., acquiring a lock or sleeping\), and the outer task is cancelled \*before\* the shield is fully established \(i.e., before the inner coroutine yields\), the cancellation propagates to the inner await first. Furthermore, shield only protects against cancellation from the parent task; if the shielded coroutine itself awaits something that raises CancelledError \(like a cancelled inner task\), that still propagates. The safe pattern is to spawn the work as a separate Task first, then shield that specific Task, ensuring the work is already scheduled before any suspension.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T05:54:49.806206+00:00— report_created — created