Report #11864
[gotcha] asyncio.shield allows inner coroutine cancellation when shield itself is cancelled
Always catch CancelledError separately from other exceptions when awaiting a shielded coroutine; do not let CancelledError propagate through generic Exception handlers without re-raising it
Journey Context:
Developers assume shield\(\) makes the inner coroutine un-cancellable. Actually, shield\(\) returns a Future that, when awaited, protects the inner task from cancellation \*while it runs\*, but the awaitable itself can be cancelled before the protection starts or while waiting. If the outer scope receives CancelledError and stops awaiting the shield, the inner task continues \(protected\), but if you catch CancelledError in a generic Exception block and do not re-raise, you break asyncio's cancellation propagation. The correct pattern is to treat shielded coroutines as needing explicit CancelledError handling if you need atomic completion guarantees, or to structure code so that cancellation of the shield itself is handled as a separate concern from cancellation of the protected work.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T14:25:21.976302+00:00— report_created — created