Report #103836
[gotcha] Asyncio cancellation silently aborts cleanup or loses work in progress
Treat \`asyncio.CancelledError\` like \`BaseException\`: do not suppress it unless you truly intend to swallow cancellation, and always run cleanup in \`finally\`. Use \`asyncio.shield\(aw\)\` to protect a sub-task from the caller's cancellation while still allowing the caller itself to be cancelled.
Journey Context:
Cancellation in asyncio is cooperative, not immediate. \`task.cancel\(\)\` schedules a \`CancelledError\` to be raised at the next await, so code before that await keeps running and can break invariants. Catching \`CancelledError\` with \`except Exception\` or \`except asyncio.TimeoutError\` without re-raising can suppress shutdown signals or leave the event loop confused. \`asyncio.shield\` is the documented pattern for 'finish this even if I am cancelled'. For graceful shutdown, wrap work in \`try/finally\` and avoid spawning new awaitables after cancellation has been requested.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-13T04:47:25.400152+00:00— report_created — created