The traceback in Python: reading the error report

The traceback is the report Python prints after an uncaught exception: it reads from the bottom up, never the other way.
5 min read
Believemy logo

Definition

A Python program that crashes never prints a single line of explanation, but a block of text that can feel overwhelming the first time you meet it. That block is not noise, though: it is the only complete account of what happened, and learning to read it saves valuable time when something breaks.

That block is called the traceback. It appears when an exception travels up uncaught, and it retraces the exact path the error took: which line triggered it, which function called that one, and so on back to the program entry point. Here is what it looks like when a lookup reaches for a key that is missing from a dictionary:

PYTHON
Traceback (most recent call last):
  File "app.py", line 42, in <module>
    total = bill(order)
  File "billing.py", line 18, in bill
    return price * order["quantity"]
KeyError: 'quantity'


It reads from the bottom up

The natural instinct is to read this block like ordinary text, from the top down. That is exactly the wrong instinct, and almost nobody says so plainly. Python stacks up blocks as the error travels from one function to the one that called it: the most recent block, the one closest to the actual cause, ends up mechanically at the bottom.

The last line gives the error type and its message: that is what happened. The block just above it gives the exact spot, with the file, the line and the faulty code: that is where it happened.

The remaining blocks, further up, tell how the program got there: the chain of functions that called one another before the error occurred. Useful for context, less so for finding the cause itself.

The diagram below lays out these three levels on the example above:

A traceback reads from the bottom upThree stacked blocks. At the bottom, the last line gives the error type and message: what happened. Just above, the file and the faulty line: where. Above that, the chain of calls: how the program got there. An arrow travels from the bottom upwards.Traceback (most recent call last):File "app.py", line 42, in <module>total = bill(order)File "billing.py", line 18, in billreturn price * order["quantity"]KeyError: 'quantity'321howwherewhatread from the bottom up: what, then where, then how

What each level tells you is summed up in this table:

Where to lookWhat you find
Last lineThe error type and its message
Block just aboveThe file, the line and the faulty code
Earlier blocksThe chain of calls, most recent to oldest
First lineThe program entry point

The "most recent call last" note, on the very first line of the traceback, confirms this reading order: the most recent call really does sit at the bottom.

Warning

A common trap is opening the file named at the very top of the traceback, expecting to find the cause there. That is almost always the wrong move: that block is the oldest one on the stack, often the program's entry point, far from where the error actually originated. The file worth opening first is the one in the block just above the last line.


Finding your own code

On a project that relies on several libraries, a good share of a traceback's blocks point to files that are not yours, but to packages installed inside a virtual environment. Scanning through all of them to find what actually broke wastes time.

The efficient reflex is to spot the last block that mentions a file from your own project. That is nearly always where the cause lives, even when the error is technically raised three levels down, inside a library.

Good to know

Since Python 3.11, the faulty line is sometimes underlined with a row of carets pointing at the exact expression at fault. A useful marker when a line chains several calls, like a().b().c(), and you need to know which of the three actually failed.

A chained exception adds a second part to the traceback, separated by a recognisable phrase. "The above exception was the direct cause of" signals a deliberate chain, written with raise ... from: the author chose to document the link between the two errors. "During handling of the above exception" instead signals an incident that happened inside an except block, with no intent to chain anything.


Getting it without crashing

Letting the traceback print to the terminal works fine during development, since someone is watching the screen. That changes as soon as the code runs unattended, inside a scheduled job or a live service: nobody reads that output, and the information disappears at the moment it would be most useful.

The standard library traceback module solves this by turning the report into plain text, retrievable with a function such as format_exc(). That text lands in a readable log instead of an output nobody watches, which keeps the error diagnosable long after it happened.


Frequently asked questions

Question

Why does my traceback not mention the real cause?

Most often because an except block caught the original error and then raised another one without explicitly linking them. Adding from to that raise restores the link: the initial cause reappears in the report, right above the new error.

Question

What does "in <module>" mean?

That the line sits at file level, outside any function. It is the body of the script, the part that runs directly at launch, without any function having been called to reach it.

Question

How can the trace be kept while execution continues?

By logging the exception inside the except block, with a logging module that records the full trace rather than a plain message. The program keeps running, and the information stays available for later diagnosis.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.