Report #103476
[gotcha] asyncio CancelledError inherits from BaseException and is swallowed or mishandled by except Exception
Never catch asyncio.CancelledError with bare except Exception. Catch Exception only for real errors and let CancelledError propagate, or catch BaseException/CancelledError explicitly if you must perform cleanup and always re-raise. Use asyncio.shield to protect critical sections from cancellation.
Journey Context:
Before Python 3.8, asyncio.CancelledError inherited from Exception, so except Exception swallowed task cancellation. In 3.8\+ it is a BaseException, matching the intent that cancellation is not an ordinary error. The subtle part is that cleanup in finally can still mask cancellation, and await inside a cancellation handler may itself be cancelled. If you need to guarantee work completes, wrap it with asyncio.shield. Also, a task cancelled while awaiting asyncio.sleep raises CancelledError immediately; ignoring it leaves the event loop in an inconsistent state.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-11T04:28:10.309921+00:00— report_created — created