Report #42950
[gotcha] asyncio CancelledError swallowed by except Exception block or cleanup code
Always catch \`asyncio.CancelledError\` explicitly before \`Exception\`, re-raise it immediately in cleanup blocks, and never suppress it with bare \`except:\` or \`except Exception:\`. Structure handlers as \`except asyncio.CancelledError: raise\` followed by \`except Exception:\` for business logic.
Journey Context:
In Python 3.8\+, \`CancelledError\` was moved from \`Exception\` to \`BaseException\` specifically to prevent it being caught by generic error handlers that clean up resources \(e.g., rolling back transactions, closing sockets\). The trap is writing \`try: ... except Exception: log\_and\_cleanup\(\)\` which silently swallows the cancellation signal, preventing the event loop from shutting down the task properly. The tradeoff is between defensive programming \(catching all errors to avoid crashes\) and cooperative concurrency \(allowing the loop to abort tasks\). The correct pattern is to treat \`CancelledError\` as a control-flow signal, not an error, and always let it propagate unless you are implementing a low-level primitive that specifically needs to transform it.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T02:33:46.293000+00:00— report_created — created