Report #104269
[gotcha] Catching BaseException or Exception in asyncio and then cancelling the task silently swallows CancelledError
Always re-raise asyncio.CancelledError in exception handlers inside async tasks. Use \`except Exception:\` instead of \`except BaseException:\` unless you explicitly intend to handle cancellation, and even then, re-raise CancelledError immediately.
Journey Context:
In Python 3.8\+, asyncio.CancelledError is a subclass of BaseException, not Exception. A common pattern is to wrap an async task in try/except to log errors, but using \`except BaseException\` or \`except Exception\` will catch CancelledError, preventing the event loop from properly cleaning up and potentially causing hangs or resource leaks. Developers often write \`except Exception as e: log\(e\)\` and wonder why tasks don't cancel. The fix is to always re-raise CancelledError: \`except CancelledError: raise\` before any other handling, or use \`except \(CancelledError,\)\` to not catch it. This is especially subtle because CancelledError was a subclass of Exception in Python 3.7 and earlier, so old code breaks silently on upgrade.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-26T20:02:44.890804+00:00— report_created — created