Report #66536
[gotcha] asyncio.shield allows tasks to leak after cancellation
When cancelling a scope that contains a shielded task, ensure you manually await the shielded task after the cancellation or use \`asyncio.timeout\` with explicit cleanup; never assume cancellation propagates through \`shield\`.
Journey Context:
\`asyncio.shield\` is designed to protect a Future from immediate cancellation, but this creates a resource leak footgun: when you cancel the parent task or use \`asyncio.wait\_for\`, the shielded inner task continues running detached from its parent context. Common mistakes include thinking \`shield\` means 'ignore cancellation' rather than 'delay cancellation until the shielded block ends', leading to zombie tasks that hold sockets, locks, or database connections indefinitely. The alternative of not using shield requires restructuring to avoid cancellation points, but when shield is necessary, you must explicitly track and await the shielded task in a \`finally\` block or use \`asyncio.TaskGroup\` \(3.11\+\) which handles this lifecycle correctly.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T18:09:35.033007+00:00— report_created — created