asyncio.CancelledError
PythonWARNINGNotableRuntime ErrorHIGH confidence

Async task was cancelled

Production Risk

Always re-raise CancelledError; swallowing it breaks graceful shutdown of async applications.

What this means

Raised inside a coroutine when it is cancelled via Task.cancel(). In Python 3.8+, CancelledError is a subclass of BaseException (not Exception), so most except Exception blocks do not catch it.

Why it happens
  1. 1task.cancel() was called on a running asyncio Task
  2. 2asyncio.wait_for() timed out and cancelled the coroutine
  3. 3TaskGroup cancelled sibling tasks after one failed
How to reproduce

An asyncio task is cancelled while running.

trigger — this will error
trigger — this will error
import asyncio

async def long_task():
    try:
        await asyncio.sleep(100)
    except asyncio.CancelledError:
        print("Task cancelled — cleaning up")
        raise  # must re-raise CancelledError

async def main():
    task = asyncio.create_task(long_task())
    await asyncio.sleep(1)
    task.cancel()
    await task

asyncio.run(main())

expected output

Task cancelled — cleaning up

Fix

Always re-raise CancelledError after cleanup

WHEN Catching CancelledError for cleanup

Always re-raise CancelledError after cleanup
async def my_task():
    try:
        await some_operation()
    except asyncio.CancelledError:
        # Do cleanup (close connections, release locks, etc.)
        await cleanup()
        raise  # MUST re-raise so the task is properly cancelled

Why this works

If CancelledError is swallowed, the task appears to complete successfully instead of being cancelled, breaking the cancel protocol.

Code examples
Triggerpython
import asyncio
async def work():
    await asyncio.sleep(100)
async def main():
    t = asyncio.create_task(work())
    await asyncio.sleep(1)
    t.cancel()  # CancelledError raised in work()
    await t
asyncio.run(main())
Handle with cleanup then re-raisepython
async def work():
    try:
        await long_operation()
    except asyncio.CancelledError:
        await cleanup()
        raise  # must re-raise
Avoid spurious cancellation with shieldpython
import asyncio
async def main():
    result = await asyncio.shield(critical_operation())
    return result
What not to do

Swallow CancelledError with a bare except or except Exception

CancelledError is BaseException — bare except catches it but except Exception does not (in 3.8+). Never silence it; always re-raise.

Version notes

Sources
Official documentation ↗

Python Docs — asyncio exceptions

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All Python errors