Yeda AI Tips · #126

Español

Always Chain Exceptions With 'from e'

Two words in Python, from e, save your 2am debugging session. Catch an error, wrap it in a nicer one, re-raise it — and if you skip the from clause, the traceback your on-call self reads at 2am points at the wrapper, not the line that actually failed. Exception chaining has been in the language since Python 3.0 (PEP 3134), and it costs you exactly two words.

The failure mode

Here's the pattern that loses information:

try:
    config = json.loads(raw)
except json.JSONDecodeError:
    raise ConfigError("invalid config file")   # original details buried

Python does keep the original exception here — as implicit context, printed under "During handling of the above exception, another exception occurred". But that message means "something else blew up while handling an error", which is ambiguous: was the second exception intentional, or a bug in your except block? Worse, tooling that only reports the final exception (many log aggregators, error trackers with default settings) shows you ConfigError: invalid config file and nothing else.

The two-word fix

try:
    config = json.loads(raw)
except json.JSONDecodeError as e:
    raise ConfigError("invalid config file") from e

Now Python attaches the original exception as __cause__ on the new one, and the traceback prints both, joined by an unambiguous line:

json.decoder.JSONDecodeError: Expecting ',' delimiter: line 3 column 9

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  ...
ConfigError: invalid config file

The wrapper gives readers context ("config loading failed"); the chained cause gives them the root cause, file, and line. No guessing, no re-running with print statements.

The three chaining modes

You writePython setsTraceback says
raise NewError(...) inside except__context__ (implicit)"During handling of the above exception, another exception occurred"
raise NewError(...) from e__cause__ (explicit)"The above exception was the direct cause of the following exception"
raise NewError(...) from Nonesuppresses contextOnly the new exception — the original is hidden

Rules of thumb: use from e whenever the new exception is a deliberate translation of the old one (the overwhelmingly common case). Use from None only when the original is genuinely noise — for example, a KeyError inside a lookup helper where "not found" is the whole story. Bare raise (no argument) re-raises the current exception untouched and needs no chaining at all.

Power-user notes

Resources

Watch the 60-second version — reel #126 in the Yeda AI Tips series — and follow for one concrete AI-coding tip per reel.

Talk to us · Read the blog · Leer en español