Moved a small scoring script from asyncio.gather to asyncio.TaskGroup, and the fallback path stopped working. Before the change, an empty weights response raised ValueError in the fetch, the except caught it, and the score was computed with default weights. After the change the same failure goes straight past the handler.
import asyncio
async def fetch_weights():
raise ValueError("weights missing")
async def main():
try:
async with asyncio.TaskGroup() as tg:
tg.create_task(fetch_weights())
except ValueError:
print("fallback weights")
asyncio.run(main())
On 3.13 this never prints. The traceback ends with ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception), and the ValueError sits inside it.
So the exception did arrive. It arrived wrapped, even with only one task failing. Before touching the handler I want to understand whether a TaskGroup always wraps like this, or only when more than one task could fail.