Report #6728
[gotcha] asyncio.shield creates orphaned task that leaks exceptions after parent cancellation
Always retain a reference to the shielded task and await it in a \`finally\` block, or explicitly cancel it if the parent is cancelled. Use \`task = asyncio.shield\(coro\)\` then \`try: ... finally: task.cancel\(\)\` or \`await task\` to retrieve exceptions.
Journey Context:
Developers use \`asyncio.shield\` to protect a critical operation \(like a database commit\) from external cancellation. Shield works by wrapping the coroutine in a new Task that is not a child of the current task in the cancellation sense. When the parent task is cancelled, the shielded task continues running independently \("orphaned"\). If the parent drops its reference to the shielded task without awaiting it, the shielded task completes but its exception \(if any\) is never retrieved, causing "Task exception was never retrieved" warnings. Additionally, if the shielded task holds resources \(connections, locks\), they remain held until it completes, potentially causing deadlocks. The fix is to treat shielded tasks as resources that must be cleaned up.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T00:46:46.971062+00:00— report_created — created