Reading Stack Traces
16 min
A Python traceback looks intimidating but has a precise structure: it lists the chain of function calls that led to the error (oldest call first, most recent last), and the VERY LAST LINE tells you the exception TYPE and MESSAGE — that's almost always where to start reading.
Traceback (most recent call last):
File "app.py", line 12, in <module>
result = process(data)
File "app.py", line 7, in process
return data[0]
IndexError: list index out of range
Read bottom-up: IndexError: list index out of range tells you WHAT
went wrong; File "app.py", line 7, in process tells you WHERE.
Catching the exception here lets you see its message programmatically -- in a real traceback (uncaught), Python prints this same message as the last line automatically.
The call chain ABOVE the last line (read bottom-to-top) shows you HOW
execution got there — useful when the error itself is generic (like
TypeError: 'NoneType' object is not subscriptable) and you need to
trace back through several function calls to find which one actually
returned None unexpectedly.
def safe_first_char(s):
if len(s) == 0:
return ""
return s[0]
Fixing the bug the traceback points at is often this simple — the hard part is genuinely reading what the traceback is telling you (exact exception type, exact line) instead of guessing or skimming past it.
Write `safe_first_char(s)`: return the first character of `s`, or an empty string if `s` is empty — fix the `IndexError` a naive `s[0]` would raise on empty input.
Write `divide_safely(a, b)`: return `a / b`, or the string `'Error: division by zero'` if `b` is 0 — catch the specific exception (`ZeroDivisionError`) a traceback would name.
When reading a Python traceback, where should you generally look FIRST to find the actual error?
You can read a traceback bottom-up (exception type/message first, then trace the call chain), and fix the specific error it identifies.