Skip to content
v0.1.0latest release21 skills2 categories3 sub-categories22 tested scripts68 reference docsContact us

Builtin Exception Hierarchy

Reference for python-exception-handling-designer · 341 lines

Programming / Pythonv1.0.0Updated OCT 20 20266 references2 scripts

The complete builtin tree (CPython 3.13/3.14), when each exception is raised, whether you should raise it yourself, and the stdlib/AI-stack exceptions you meet most often. Version tags mark additions and changes.

Contents

The tree

text
BaseException
 ├── BaseExceptionGroup                       (3.11)
 ├── GeneratorExit
 ├── KeyboardInterrupt
 ├── SystemExit
 └── Exception
      ├── ArithmeticError
      │    ├── FloatingPointError
      │    ├── OverflowError
      │    └── ZeroDivisionError
      ├── AssertionError
      ├── AttributeError
      ├── BufferError
      ├── EOFError
      ├── ExceptionGroup [BaseExceptionGroup]  (3.11)
      ├── ImportError
      │    └── ModuleNotFoundError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── MemoryError
      ├── NameError
      │    └── UnboundLocalError
      ├── OSError
      │    ├── BlockingIOError
      │    ├── ChildProcessError
      │    ├── ConnectionError
      │    │    ├── BrokenPipeError
      │    │    ├── ConnectionAbortedError
      │    │    ├── ConnectionRefusedError
      │    │    └── ConnectionResetError
      │    ├── FileExistsError
      │    ├── FileNotFoundError
      │    ├── InterruptedError
      │    ├── IsADirectoryError
      │    ├── NotADirectoryError
      │    ├── PermissionError
      │    ├── ProcessLookupError
      │    └── TimeoutError
      ├── ReferenceError
      ├── RuntimeError
      │    ├── NotImplementedError
      │    ├── PythonFinalizationError        (3.13)
      │    └── RecursionError
      ├── StopAsyncIteration
      ├── StopIteration
      ├── SyntaxError
      │    └── IndentationError
      │         └── TabError
      ├── SystemError
      ├── TypeError
      ├── ValueError
      │    └── UnicodeError
      │         ├── UnicodeDecodeError
      │         ├── UnicodeEncodeError
      │         └── UnicodeTranslateError
      └── Warning
           ├── BytesWarning
           ├── DeprecationWarning
           ├── EncodingWarning                (3.10)
           ├── FutureWarning
           ├── ImportWarning
           ├── PendingDeprecationWarning
           ├── ResourceWarning
           ├── RuntimeWarning
           ├── SyntaxWarning
           ├── UnicodeWarning
           └── UserWarning

Not builtins but critical: asyncio.CancelledError and concurrent.futures.CancelledError derive from BaseException since 3.8 (they used to be Exception), so except Exception no longer catches cancellation.

Aliases: IOError and EnvironmentError are OSError; socket.error is OSError; socket.timeout is TimeoutError (3.10); asyncio.TimeoutError and concurrent.futures.TimeoutError are TimeoutError (3.11).

Print the tree for your interpreter:

python
def tree(cls: type, indent: int = 0) -> None:
    print(" " * indent + cls.__name__)
    for sub in sorted(cls.__subclasses__(), key=lambda c: c.__name__):
        if sub.__module__ == "builtins":
            tree(sub, indent + 2)


tree(BaseException)

BaseException branch: never swallow

ExceptionRaised byCorrect handling
KeyboardInterruptSIGINT (Ctrl+C) in the main threadLet it propagate; a CLI may convert it to exit code 130 at the very top
SystemExitsys.exit(), argparse errors, raise SystemExit(code)Let it propagate; test it with pytest.raises(SystemExit)
GeneratorExitgenerator.close(), garbage collection of a suspended generatorClean up and return/raise; never yield after it (RuntimeError)
asyncio.CancelledErrortask.cancel(), timeouts, TaskGroup siblings failing, server shutdownClean up, then raise
BaseExceptionGroupTaskGroup/except* when a member is a BaseExceptionHandle with except* per member type

Catch BaseException only to run cleanup and re-raise:

python
def run_training(model, loader, ckpt_path: str) -> None:
    try:
        train(model, loader)
    except BaseException:
        save_checkpoint(model, ckpt_path)  # also on Ctrl+C: resume later
        raise

Exception subclasses: when each is raised

ExceptionTypical triggerRaise it yourself?
ArithmeticErrorbase of numeric errorscatch only
OverflowErrormath.exp(1000), float -> int of infrarely
ZeroDivisionErrorx / 0, x % 0no; validate the divisor instead
FloatingPointErrornumpy with np.seterr(all="raise")no
AssertionErrorfailing assertonly in tests and invariant checks
AttributeErrormissing attribute; also from __getattr__yes, from __getattr__
BufferErrorresizing a buffer with exported viewsno
EOFErrorinput() at end of stdin, asyncio.IncompleteReadErrorrarely
ImportError / ModuleNotFoundErrormissing optional dependencycatch to give an install hint
LookupErrorbase of Index/KeyErroryes, for custom containers (catch the base)
IndexErrorsequence index out of rangeyes, in __getitem__
KeyErrormissing mapping keyyes, in mapping types; message is repr(key)
MemoryErrorhost allocation failureno; recovery is rarely possible
NameError / UnboundLocalErrorundefined variablenever handle; a bug
NotImplementedErrorabstract method placeholdersyes (do not confuse with the NotImplemented constant)
RecursionErrorrecursion limit exceededno
RuntimeErrorgeneric "cannot happen now" state; also torch.cuda.OutOfMemoryError baseprefer a specific subclass
StopIterationnext() on an exhausted iteratoronly inside __next__; inside a generator it becomes RuntimeError (PEP 479)
StopAsyncIteration__anext__ exhaustiononly inside __anext__
SyntaxErrorcompile(), ast.parse(), eval()when you parse a DSL; set filename/lineno
SystemErrorinterpreter bugnever
TypeErrorwrong type, wrong arg count, unhashableyes, for wrong argument types
ValueErrorright type, bad value (int("x"), json.loads(""))yes, the default for bad input
UnicodeDecodeErrorbytes.decode failure, reading a file with the wrong encodingcatch; decode with errors="replace" when lossy is OK

KeyError quirk

str(KeyError("model")) is "'model'" (the repr). Read err.args[0] for the key:

python
try:
    price = PRICES[model_name]
except KeyError:
    raise ConfigurationError(f"no price configured for model {model_name!r}") from None

OSError and errno

OSError(errno, strerror[, filename]) is auto-mapped to a subclass by errno:

errnoSubclass
EAGAIN, EWOULDBLOCK, EINPROGRESSBlockingIOError
ECHILDChildProcessError
EPIPE, ESHUTDOWNBrokenPipeError
ECONNABORTEDConnectionAbortedError
ECONNREFUSEDConnectionRefusedError
ECONNRESETConnectionResetError
EEXISTFileExistsError
ENOENTFileNotFoundError
EINTRInterruptedError (auto-retried by the stdlib since 3.5, PEP 475)
EISDIR / ENOTDIRIsADirectoryError / NotADirectoryError
EACCES, EPERMPermissionError
ESRCHProcessLookupError
ETIMEDOUTTimeoutError
python
import errno
import os

try:
    os.makedirs(cache_dir)
except FileExistsError:
    pass  # fine: the cache already exists (better: os.makedirs(cache_dir, exist_ok=True))
except OSError as err:
    if err.errno == errno.ENOSPC:
        raise ResourceExhaustedError("disk full while writing embedding cache", device=cache_dir) from err
    raise

OSError attributes: errno, strerror, filename, filename2, winerror (Windows).

Warnings

CategoryShown by default?Use for
UserWarningyesdefault for warnings.warn
DeprecationWarningonly in __main__ and testsAPI being removed (audience: developers)
PendingDeprecationWarningnowill be deprecated later
FutureWarningyesbehaviour change aimed at end users (pandas style)
RuntimeWarningyesdubious runtime values (numpy overflow)
ResourceWarningno (enable with -X dev)unclosed files/sockets/clients
SyntaxWarningyesdubious syntax (is with literal, return in finally in 3.14)
EncodingWarningopt-in -X warn_default_encoding (3.10)open() without encoding=
python
import warnings


def retrieve(query: str, top_k: int = 5):
    if top_k > 100:
        warnings.warn(f"top_k={top_k} is slow and rarely improves answers", RuntimeWarning, stacklevel=2)
    ...

Python 3.13 adds warnings.deprecated (also in typing_extensions) as a decorator that warns at call time and is understood by type checkers.

Which builtin should I raise?

SituationRaise
Argument has the wrong typeTypeError
Argument has the right type but invalid value (temperature=5)ValueError
Key/ID not found in your registryKeyError / LookupError (or a domain NotFoundError)
Object in wrong state (client.chat() before connect())RuntimeError or a domain error
Subclass must implementNotImplementedError
Operation timed outTimeoutError (or a domain subclass)
Feature not available on this platform/configdomain ConfigurationError
Anything a caller should handle differentlya domain exception

Never raise Exception, BaseException, SystemError, NameError, or AssertionError for input validation.

A domain error may also inherit a builtin so callers who only know builtins still catch it:

python
class InputValidationError(RagkitError, ValueError):
    """Bad caller input; also a ValueError for generic callers."""

Common stdlib and third-party exceptions

ExceptionBaseNotes
json.JSONDecodeErrorValueError.msg, .doc, .pos, .lineno, .colno - feed back to the model in repair loops
subprocess.CalledProcessErrorSubprocessError.returncode, .stderr (with check=True)
subprocess.TimeoutExpiredSubprocessErrornot a TimeoutError
asyncio.CancelledErrorBaseException (3.8+)always re-raise
asyncio.TimeoutErrorTimeoutError (3.11+), Exception beforecatch TimeoutError on 3.11+
asyncio.InvalidStateErrorExceptionresult of an unfinished future
asyncio.IncompleteReadErrorEOFError.partial bytes received
concurrent.futures.BrokenExecutorRuntimeErrorworker process died (OOM-killed)
pickle.PicklingErrorPickleErrorcustom exceptions with kw-only __init__ without __reduce__
ssl.SSLErrorOSErrorTLS failures to model gateways
httpx.TimeoutExceptionhttpx.TransportError -> RequestError -> HTTPErrorConnect/Read/Write/PoolTimeout
httpx.HTTPStatusErrorHTTPErrorfrom response.raise_for_status(); .response.status_code
requests.RequestExceptionOSError (IOError)ConnectionError, Timeout, HTTPError subclasses
pydantic.ValidationErrorValueError (v2).errors() list, .json()
openai.APIErrorOpenAIErrorsubclasses APIConnectionError, APITimeoutError(APIConnectionError), APIStatusError -> RateLimitError, BadRequestError, AuthenticationError, InternalServerError...
anthropic.APIStatusErrorAPIErrorRateLimitError (429), InternalServerError (5xx; 529 overloaded has its own subclass in newer SDK versions), .status_code, .response.headers
torch.cuda.OutOfMemoryErrorRuntimeErrortorch >= 1.13; older versions raise plain RuntimeError("CUDA out of memory")

Check an SDK's tree at runtime instead of guessing:

python
import inspect
import openai

for name, cls in inspect.getmembers(openai, inspect.isclass):
    if issubclass(cls, BaseException):
        print(f"{name:35} {' -> '.join(c.__name__ for c in cls.__mro__[1:-2])}")

Exception object anatomy

AttributeMeaning
argstuple passed to the constructor; str(e) uses it
__traceback__traceback object (frames); keep exceptions short-lived to avoid reference cycles
__cause__explicit cause from raise ... from cause
__context__implicit context: the exception being handled when this one was raised
__suppress_context__set by from (including from None): hides __context__ in the traceback
__notes__list of strings added by add_note() (3.11)
with_traceback(tb)returns self with a replaced traceback
python
import traceback


def describe(err: BaseException) -> dict:
    """Serialise an exception chain for an error-tracking payload."""
    chain = []
    cur = err
    while cur is not None:
        chain.append({"type": type(cur).__qualname__, "message": str(cur),
                      "notes": list(getattr(cur, "__notes__", []))})
        cur = cur.__cause__ or (None if cur.__suppress_context__ else cur.__context__)
    return {"chain": chain, "traceback": "".join(traceback.format_exception(err))}

traceback.format_exception(err) with a single argument works on 3.10+; on 3.9 pass (type(err), err, err.__traceback__).

The variable bound by except E as err: is deleted at the end of the handler (to break the frame cycle). Copy it to another name if you need it later:

python
last_error = None
for attempt in range(3):
    try:
        return call()
    except TimeoutError as err:
        last_error = err
raise ProviderTimeoutError("3 attempts timed out") from last_error

Version changes that matter

VersionChange
3.8asyncio.CancelledError becomes a BaseException
3.10socket.timeout is an alias of TimeoutError; EncodingWarning; better error messages ("Did you mean ...")
3.11ExceptionGroup, BaseExceptionGroup, except*; add_note/__notes__; asyncio.TaskGroup, asyncio.timeout; asyncio.TimeoutError is TimeoutError; fine-grained traceback locations; zero-cost try
3.12sys.last_exc; sys.exception() (3.11) preferred over sys.exc_info()
3.13PythonFinalizationError; warnings.deprecated; colourised tracebacks
3.14return/break/continue in finally emit SyntaxWarning (PEP 765); except A, B: without parentheses allowed when no as (PEP 758)
More in Python

python-beginner-concept-tutor

Teach Python concepts to beginners heading into AI engineering (data scientists, analysts, students, career switchers): plain-language definitions, analogies, minimal examples, line-by-line walkthroughs, common mistakes, check-your-understanding questions and mini exercises; Socratic hints before solutions; explaining tracebacks; mutable vs immutable, references and aliasing, is vs ==, integer division, floating point, slicing and off-by-one, indentation errors; a staged learning path from variables to calling an LLM API, embeddings and a tiny RAG. Ships a script that lists the concepts a snippet uses in learning order and traces execution step by step like Python Tutor.

python-comprehension-refactorer

Refactor Python loops into list, dict and set comprehensions and generator expressions, and unroll comprehensions that are too clever: filtering, mapping, nested-loop flattening, conditional expressions, walrus in comprehensions, dict inversion, grouping with defaultdict/Counter, lazy generators for sum/any/all/max, streaming large files, itertools (chain, islice, groupby, batched, pairwise, accumulate, product), scoping rules, side-effect anti-patterns and performance (when map/filter or numpy/pandas vectorization win). AI-engineering focus: building prompt lists, batching texts for embeddings, filtering retrieved chunks by score, id->embedding dicts, flattening tool-call results, lazy dataset streaming and token counting.

python-context-manager-writer

Write correct Python context managers and find resource-handling bugs — __enter__/__exit__ semantics and exception suppression, contextlib (contextmanager, asynccontextmanager, ExitStack, AsyncExitStack, closing, aclosing, suppress, redirect_stdout, nullcontext, chdir), async with, re-entrancy, leaked files/connections/clients/pools/locks, and AI-engineering recipes: torch.no_grad/inference_mode/autocast, eval()/train() switches, GPU cache cleanup, token and latency meters, tracing spans, temp env vars, rate-limit semaphores, httpx/aiohttp client lifecycle, FastAPI lifespan, DB/vector-store transactions, atomic checkpoint writes, seeds and agent sandboxes.

python-dataclass-converter

Convert boilerplate Python classes, dicts, tuples and JSON payloads into dataclasses, or into pydantic v2 BaseModel, TypedDict, NamedTuple, attrs or msgspec when that fits better. Covers every @dataclass option (frozen, slots, kw_only, order, unsafe_hash, match_args, weakref_slot), field() (default_factory, init=False, repr, compare, hash, metadata), __post_init__, InitVar, KW_ONLY, inheritance and default ordering, replace(), asdict deep-copy pitfalls, hashing/equality, serialization and validation. AI focus: LLM request/response and chat Message types, RAG chunks with embeddings (numpy eq gotcha), eval records, configs, typed OpenAI/Anthropic JSON.

python-idiomatic-code-reviewer

Review Python code for non-idiomatic, unpythonic or risky patterns and rewrite it into clean modern Python: PEP 8 / PEP 20, EAFP vs LBYL, iteration idioms (enumerate, zip, comprehensions, any/all), unpacking, f-strings, pathlib, truthiness, `is None`, mutable defaults, walrus, match statements, collections / itertools / functools, logging instead of print, with-blocks and resource handling. Includes AI-engineering checks: hardcoded API keys, time.sleep or requests inside async def, missing HTTP timeouts, unbounded retry loops, model clients built at import time, prompt string concatenation, sequential awaits, eval() on LLM output. Ships a 46-rule AST reviewer with severities and suggested rewrites.

python-type-hints-annotator

Add accurate, modern type hints to Python and fix mypy / pyright (pyrefly, ty) errors: builtin generics, X | None, TypeAlias and the 3.12 type statement, TypeVar and PEP 695 generics, Protocol, Callable / ParamSpec / Concatenate, TypedDict (Required, NotRequired, ReadOnly), Literal, Final, ClassVar, overload, Annotated, TypeGuard / TypeIs, Self, Never, TypeVarTuple, async types, Iterable vs Sequence vs Mapping, TYPE_CHECKING, stubs, py.typed, gradual strictness. AI-engineering focus: typed LLM message dicts and tool schemas, pydantic vs TypedDict, numpy NDArray, torch / jaxtyping shapes, streaming generators, async clients, callbacks, generic VectorStore protocols, typed config. Ships an AST audit: coverage gate, legacy-typing rewrites, inferred types.