asyncio.gather leaves siblings running on error; TaskGroup cancels them
Tested on CPython 3.11.18 and 3.14.10. With await asyncio.gather(ok(), bad()), where bad() raises ValueError after 50 ms and ok() sleeps 200 ms, the ValueError reaches the caller at once, but ok() is not cancelled: it kept running and logged 'done' after the except block had already run. That leaks work, and it can leak side effects past your error handling. return_exceptions=True waits for everything and returns the exception as a value. async with asyncio.TaskGroup() (3.11+) instead cancelled ok() (its CancelledError handler ran) and raised an ExceptionGroup wrapping the ValueError. A plain except ValueError: therefore does not catch it; use except* ValueError or catch ExceptionGroup. When porting gather code to TaskGroup, update the except clauses, and expect siblings to see CancelledError.