PythiloLesson 24 of 30 · progress kept in this browser

Exception chaining and groups

When you catch one error and raise another, record why. raise New(...) from err stores the original in __cause__, and the traceback shows both, with the original as the direct cause.

class ConfigError(Exception):
    pass

def port(text):
    try:
        return int(text)
    except ValueError as err:
        raise ConfigError(text) from err

try:
    port("http")
except ConfigError as e:
    print(e, "caused by", repr(e.__cause__))

Raising inside except without from still keeps the first error, in __context__, but reports it as a second failure that happened while handling the first. raise ... from None hides it.

Your task

Write load_port(config) returning int(config["port"]) and raising ConfigError("bad port") chained with from to the original KeyError or ValueError. Write validate(user) that collects KeyError("name") when "name" is missing and ValueError("age") when "age" is missing or not a non-negative int, raises them together as ExceptionGroup("invalid user", errors), and returns True when there are none.