← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Exception Groups & except*

python Python 3.11+ Advanced
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7) — mypy/ruff don't reliably flag 'only first exception caught' patterns in asyncio.gather; missed concurrent failures typically surface in code review or when failures slip through silently.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3) — quick_fix is replacing asyncio.gather with TaskGroup and using except* blocks, a localized pattern swap within the affected async code paths.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3) — applies primarily to async/concurrent code sections; doesn't shape the whole system but adds ongoing handling complexity wherever TaskGroup is used.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7) — per misconception, developers assume except* is a drop-in for except; it contradicts familiar exception semantics by operating on groups and leaving unmatched exceptions to propagate.

About DEBT scoring →

Also Known As

ExceptionGroup except* Python 3.11 exceptions concurrent exceptions ExceptionGroup Python

TL;DR

Python 3.11+ ExceptionGroup allows multiple concurrent exceptions to be raised simultaneously — essential for asyncio.TaskGroup where all tasks run even if some fail.

Explanation

ExceptionGroup (Python 3.11) wraps multiple exceptions raised simultaneously. except* syntax catches specific exception types from the group while letting unmatched exceptions propagate. asyncio.TaskGroup (Python 3.11) runs all tasks and collects all failures in an ExceptionGroup — unlike asyncio.gather which only surfaces the first failure. The except* handler receives an ExceptionGroup containing only the matching exceptions.

Common Misconception

except* catches individual exceptions like except — except* specifically handles ExceptionGroup and collects all matching exceptions from the group; it does not replace regular except for single-exception handling.

Why It Matters

asyncio.TaskGroup exposes all concurrent failures simultaneously — without ExceptionGroup, only the first failure from concurrent tasks would be visible, hiding other errors.

Common Mistakes

  • Using except* for single exceptions — it is specifically for ExceptionGroup
  • Not handling remaining unmatched exceptions — they still propagate
  • Forgetting asyncio.TaskGroup requires Python 3.11+ — use asyncio.gather for older versions
  • Not iterating eg.exceptions to see individual exception details

Code Examples

✗ Vulnerable
# asyncio.gather — only first error visible:
async def run_all():
    results = await asyncio.gather(task1(), task2(), task3())
    # If task1 and task3 both fail:
    # Only task1's error is raised — task3's error is silently lost
✓ Fixed
# asyncio.TaskGroup — all errors collected:
async def run_all():
    async with asyncio.TaskGroup() as tg:
        t1 = tg.create_task(task1())
        t2 = tg.create_task(task2())
        t3 = tg.create_task(task3())
    # All tasks ran; both failures collected in ExceptionGroup

try:
    await run_all()
except* ValueError as eg:
    for exc in eg.exceptions:
        print(f'ValueError from task: {exc}')
except* ConnectionError as eg:
    for exc in eg.exceptions:
        print(f'Connection failed: {exc}')

Added 16 Mar 2026
Edited 22 Mar 2026
Views 48
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 2 pings S 0 pings S 0 pings M 3 pings T 0 pings W 1 ping T 2 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 17 Perplexity 6 Google 4 ChatGPT 3 Ahrefs 2 Unknown AI 1
crawler 33
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Use Python 3.11 ExceptionGroups with except* to handle multiple concurrent exceptions — essential when running parallel async tasks where several may fail simultaneously
📦 Applies To
python 3.11 web cli
🔗 Prerequisites
🔍 Detection Hints
asyncio.gather() catching only first exception; ignoring failures from asyncio.TaskGroup; no handling for concurrent task failures
Auto-detectable: ✓ Yes mypy ruff
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update

✓ schema.org compliant