Read and Understand Python Tracebacks

Learn how to read Python tracebacks line by line, identify the root cause of errors, and use traceback information to debug faster.

7 min read

A Python traceback looks intimidating the first time you see one. Lines of file paths, line numbers, and cryptic function names fill the terminal in red.

But a traceback is the most useful debugging output Python can give you. It tells you exactly which line triggered the error, what kind of error occurred, and the complete path your program took to reach that point.

This article teaches you to read a traceback line by line. It assumes you have seen error messages before and are comfortable with reading Python error messages. By the end, the red text will stop looking like noise and start looking like a map.

Anatomy of a traceback

Every traceback has the same structure, regardless of the exception type or the complexity of your program. Here is a traceback from a program that tries to read a missing configuration file:

texttext
Traceback (most recent call last):
  File "main.py", line 10, in <module>
    start_app()
  File "main.py", line 6, in start_app
    config = load_config("settings.json")
  File "config.py", line 3, in load_config
    with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: 'settings.json'

Start at the bottom. The last line tells you the exception type and the human-readable message.

This program raised a FileNotFoundError because a file named settings.json does not exist. That alone often tells you what to fix.

Move up one line. This is the frame where the exception occurred: line 3 of config.py, inside the function named load_config. The line with open(filename) as f: tried to open the file and failed.

Continue upward. The frame above shows that load_config was called from line 6 of main.py, inside the function named start_app. The function passed the filename "settings.json" as an argument.

The top frame shows the entry point: line 10 of main.py called start_app in the first place. The traceback reads like a stack of function calls, with the most recent call at the bottom and the program entry point at the top.

Reading bottom to top

The natural reading order for a traceback is from bottom to top. The bottom tells you what went wrong. Each step upward explains why the program was executing that code in the first place.

In simple scripts with one or two function calls, the middle frames may not add much. But in larger programs where the same utility function is called from many places, the middle frames are essential. They tell you which caller passed the bad argument, which conditional branch was taken, and which sequence of events led to the error.

A common mistake is reading only the last line and guessing at the cause. The last line tells you the FileNotFoundError occurred.

The frame above tells you the filename was "settings.json", not "config.json" or "defaults.json". That distinction is what turns a five-minute debugging session into a thirty-second fix.

Understanding frame information

Each frame in a traceback contains four pieces of information:

  • The file path tells you which module contains the problematic code.
  • The line number pinpoints the exact line.
  • The function or module name tells you the context.
  • The code snippet shows the line that was executing.

When a frame references a third-party library or the standard library, the problem is almost never in that library. It is in the arguments your code passed to it.

Focus on the bottommost frame that references a file you wrote. That is where your code made a decision that led to the error.

If every frame references your own code, start at the bottom and work upward until you understand the full sequence. Pay attention to variable values that appear in the code snippets.

A line like result = data[key] that raises a KeyError tells you the key was missing from the dictionary. The frame above tells you where the dictionary came from.

Common exception types in tracebacks

Recognizing exception types speeds up diagnosis. A NameError means you referenced a variable that does not exist.

A TypeError means you used an operation on an incompatible type, like adding a string to an integer. A ValueError means the type was correct but the value was inappropriate, like passing a negative number to a function expecting a positive one.

An IndexError means you accessed a list position that does not exist. A KeyError means you accessed a dictionary key that is not present. An AttributeError means you tried to access an attribute or method that the object does not have.

An ImportError or ModuleNotFoundError means Python could not find a module you tried to import. This is usually a path issue or a missing dependency, not a logic error in your code.

Chained exceptions

Python can show multiple tracebacks stacked together when an exception occurs while handling another exception. The output starts with the original traceback, followed by a line that reads "During handling of the above exception, another exception occurred", and then the second traceback.

texttext
Traceback (most recent call last):
  File "app.py", line 5, in process
    value = int(user_input)
ValueError: invalid literal for int() with base 10: 'abc'
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "app.py", line 7, in process
    log_error(f"Bad input: {user_input}")
NameError: name 'log_error' is not defined

The first exception shows the original problem: the user entered text that cannot be converted to an integer. The second exception shows a bug in the error handler: the function log_error was misspelled. Both are relevant, and both need fixing.

Using the traceback module

Python's traceback module lets you capture and format tracebacks programmatically. This is useful for logging errors to a file or displaying them in a user interface without crashing the program.

pythonpython
import traceback
 
try:
    result = 10 / 0
except ZeroDivisionError:
    formatted = traceback.format_exc()
    print("An error occurred:")
    print(formatted)

The format_exc function returns the same text you would see in the terminal. Use print_exc to print it directly without capturing the string. Use extract_tb to get structured data from a traceback object for programmatic analysis.

Tracebacks in test output

When a test fails with an unexpected exception, the traceback appears in the test output. Read it the same way you would read a runtime traceback. The test framework adds its own frames at the top, but the frames from your code are in the middle.

Focus on the first frame that references your source code, not the test framework. If the traceback points to an assertion method like assertEqual, the problem is that the values did not match. The frame above the assertion shows which test method called it and what values were compared.

The next article covers finding slow Python code while debugging, which helps when your code runs correctly but takes too long.

Rune AI

Rune AI

Key Insights

  • Read tracebacks from bottom to top: the last line is the exception type and message, the line above is where it occurred.
  • Each frame shows the file, line number, function name, and the code that was executing when the next function was called.
  • Focus on frames that reference your own code first; standard library frames are rarely the root cause.
  • Chained exceptions show the original error followed by a second error that occurred during handling.
  • The traceback module lets you format and print tracebacks programmatically for logging and error reporting.
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between the bottom and top of a traceback?

The bottom of a traceback shows where the exception actually occurred: the exact line that raised the error. The top shows where the program started. Each line in between represents a function call that led to the error. Read from bottom to top: start at the exception, then work upward to understand the sequence of calls that caused it.

How do I read a traceback when my code spans multiple files?

Each frame in the traceback shows the file path, line number, function name, and the line of code. The file path tells you which module the error is in. If you see paths from third-party packages or the standard library, the problem is likely in how your code calls those libraries, not in the library itself. Focus on the bottommost frame that points to your own code.

Why does Python sometimes show chained exceptions with 'During handling of the above exception'?

This happens when an exception occurs inside an except block. Python shows the original exception first, then the new exception that occurred while handling it. Both are relevant. The original exception tells you what went wrong initially. The second exception tells you that your error handling code also failed, often because it made an incorrect assumption about the original error.

Conclusion

A traceback is not a wall of red text to fear. It is a structured report that tells you exactly what went wrong, where it happened, and how the program reached that point. Learn to read it bottom to top, focus on your own code, and use it as your first debugging tool.