Free Python reference · JavaScript timeline

Python 3.11: Handle grouped failures and inspect errors

Exception groups, structured async tasks, TOML parsing, and more precise tracebacks improve everyday diagnostics.

Released · Editorial review October 25, 2026

Introduced in Python 3.11 · Syntax

ExceptionGroup and except*

An exception group packages several exceptions into one failure. This is useful when independent work can fail in several places. except* selects matching members, including members of nested groups, rather than treating the whole group as a single ordinary exception.

Separate handlers can process different exception types. Each matching handler receives a subgroup; unhandled members continue propagating. Ordinary except ValueError does not mean “find ValueErrors inside this group.”

The example constructs a small flat group so the counts are easy to inspect. In application code, handle only the failures you understand and let unexpected errors remain visible.

Worked example

Minimum Python 3.11

try:
    raise ExceptionGroup("batch", [ValueError("bad count"), TypeError("bad shape")])
except* ValueError as group:
    print("value errors:", len(group.exceptions))
except* TypeError as group:
    print("type errors:", len(group.exceptions))

Expected output

value errors: 1
type errors: 1

Example checked with CPython 3.14.8, CPython 3.15.0, Pyodide Python 3.13.2.

Common mistake

Do not mix except and except* handlers on the same try statement. Handling a matching subgroup does not suppress unrelated exceptions.

Try it yourself

Add a second ValueError and predict the first count. Then consider what propagates if the TypeError handler is removed.

Read more: Python 3.11 release notes · PEP 654

Introduced in Python 3.11 · Standard library

TaskGroup gives related tasks a boundary

An asyncio.TaskGroup owns tasks created within an asynchronous context manager. Leaving the context waits for those tasks. If a task fails with an ordinary exception, the group cancels remaining tasks and reports failures through an exception group after cleanup.

This makes task lifetime explicit: a caller knows when related work has finished. Cancellation remains cooperative, so coroutines must allow it to propagate after any cleanup.

The example gathers two independent results and combines them only after the group exits. Run it as a native script; notebook and browser event loops have their own entry-point rules.

Worked example

Minimum Python 3.11 · Run locally

import asyncio

async def twice(number):
    await asyncio.sleep(0)
    return number * 2

async def main():
    async with asyncio.TaskGroup() as group:
        first = group.create_task(twice(2))
        second = group.create_task(twice(5))
    return first.result() + second.result()

print(asyncio.run(main()))

Expected output

14

Example checked with CPython 3.14.8, CPython 3.15.0.

Common mistake

TaskGroup does not make CPU-bound work parallel. Swallowing CancelledError can interfere with structured cancellation.

Try it yourself

Make one coroutine raise ValueError. Explain why the combined result should not be used as though every task succeeded.

Read more: Python 3.11 release notes

Introduced in Python 3.11 · Standard library

Read TOML with tomllib

tomllib reads TOML into Python values without an extra package. TOML commonly appears in configuration files such as pyproject.toml. Parsing from a string uses loads; loading from a file uses a binary file object with load.

Parsed integers become integers and sections become dictionaries. Parsing verifies TOML syntax, but it does not prove the configuration has all the fields your application requires. Validate required keys and acceptable values after parsing.

The example uses a string so it needs no filesystem access. The standard module reads TOML; it does not provide a TOML-writing API.

Worked example

Minimum Python 3.11

import tomllib

config = tomllib.loads('[report]\nname = "weekly"\nlimit = 5\n')
print(config["report"]["name"])
print(config["report"]["limit"] + 1)

Expected output

weekly
6

Example checked with CPython 3.14.8, CPython 3.15.0, Pyodide Python 3.13.2.

Common mistake

Text-mode files are not accepted by tomllib.load(). TOML syntax checks are different from validating the application-specific configuration schema.

Try it yourself

Change limit to a quoted string. Predict which line now fails and where validation should catch that mistake.

Read more: Python 3.11 release notes · PEP 680

Introduced in Python 3.11 · Interpreter capability

Tracebacks can point inside expressions

CPython 3.11 records finer source positions so a traceback can identify a failing subexpression within a longer line. This helps distinguish a missing record field from a problem in a later arithmetic operation.

The exact display depends on the interpreter, terminal, available source text, and configuration. The script below prints the exception type deterministically. To inspect source-position markers, temporarily remove the try/except and run the saved script in a normal terminal.

Use the traceback as a lead, then reduce the failing input and keep a regression case. A highlighted expression does not explain which input rule the program violated.

Worked example

Minimum Python 3.11 · Run locally

record = {"count": None}
try:
    total = record["count"] + 1
except TypeError as error:
    print(type(error).__name__)

Expected output

TypeError

The printed exception name is tested. Traceback underline/color is a native-interpreter display feature and is not a portable expected-output contract.

Example checked with CPython 3.14.8, CPython 3.15.0.

Common mistake

Do not write tests against exact traceback spacing or color. Catching and ignoring every TypeError can hide unrelated defects.

Try it yourself

Remove the handler and inspect the traceback. Then change record to {} and explain why the failure type changes.

Read more: Python 3.11 release notes · PEP 657

Recap

Exception groups, structured async tasks, TOML parsing, and more precise tracebacks improve everyday diagnostics. Prefer the clearest form that works on your project's supported Python versions.

Read the full Python 3.11 release notes →