Report #104340
[gotcha] Python's \`except Exception\` does NOT catch \`asyncio.CancelledError\` in Python 3.8\+ — but \`except BaseException\` does, and that can silently swallow task cancellation.
Never catch \`BaseException\` or bare \`except:\` in asyncio code unless you re-raise \`CancelledError\` immediately. If you must catch broad exceptions for cleanup, use \`except Exception\` and then add a separate \`except asyncio.CancelledError: raise\` block. For cleanup in \`finally\`, always check for cancellation and re-raise.
Journey Context:
In Python 3.8, \`asyncio.CancelledError\` was changed to inherit from \`BaseException\` instead of \`Exception\` \(bpo-32528\). This means code that used \`except Exception\` to wrap async tasks would no longer catch cancellation — which is good, because swallowing cancellation prevents task shutdown. But the flip side is that code written with \`except BaseException\` \(often for logging\) will now silently swallow cancellation, leaving coroutines stuck mid-flight. The classic bug: a \`finally\` block that does cleanup and then a \`return\` or \`raise\` different exception, which prevents the \`CancelledError\` from propagating. The correct pattern is to always re-raise \`CancelledError\` unless you are deliberately handling it \(e.g., to perform async cleanup before cancelling\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-08-02T20:05:51.779322+00:00— report_created — created