With its default error behavior, asyncio.gather propagates the first exception to its awaiter without automatically cancelling other submitted awaitables.
Python asyncio.gather: a sibling can continue after the first failure
Operation contract
The failing receipt job raises immediately. Its sibling is already waiting on a gate. After gather raises, the caller checks that the sibling task is still pending, then opens the gate and awaits it. This makes the lifetime visible rather than relying on a scheduling sleep. The caller owns cleanup of a task it intentionally allowed to continue.
Failure and ownership boundary
A cancelled gather future and a child cancellation follow different rules, and another child may also fail later. TaskGroup applies a different sibling-cancellation contract. Choose one explicitly before starting work with side effects. Python asyncio TaskGroup: cancel sibling work and retain failure evidence, Python asyncio timeout: cancellation and cleanup ownership and Python cancellation review: release a permit before propagating task cancellation provide the comparison.
Working program
import asyncio
async def reject_receipt():
raise ValueError("invalid receipt")
async def delayed_receipt(gate):
await gate.wait()
return "R42 stored"
async def main():
gate = asyncio.Event()
sibling = asyncio.create_task(delayed_receipt(gate))
try:
await asyncio.gather(reject_receipt(), sibling)
except ValueError:
print("sibling pending:", not sibling.done())
gate.set()
print("sibling result:", await sibling)
asyncio.run(main())Output
sibling pending: True
sibling result: R42 storedCosts and limits
Task creation and scheduling add runtime work; the fixture runs two tasks. A real batch needs a bound on in-flight tasks and explicit handling of every task result or failure. A continuing sibling may already have side effects when the caller sees the first error.
Common Mistakes
- Do not assume gather cancels every sibling on the first ordinary exception.
- Retain and observe tasks that continue after an early failure.
Connected lessons
Python asyncio TaskGroup: cancel sibling work and retain failure evidence, Python asyncio timeout: cancellation and cleanup ownership, Python cancellation review: release a permit before propagating task cancellation.
Continue with Python eager asyncio tasks: a coroutine can finish before create_task returns.
