DEV Community

Cover image for Python Error Messages Are Telling You Exactly What Is Wrong. Here Is How to Read Them.
Ameer Abdullah
Ameer Abdullah

Posted on

Python Error Messages Are Telling You Exactly What Is Wrong. Here Is How to Read Them.

Most beginners read a Python error message, see a long red block of text, and go straight to Stack Overflow without understanding what they already have in front of them.

The error message is telling you the exact file, the exact line, and the exact nature of the problem. Once you know how to read the structure, you can diagnose most bugs without searching.


The Anatomy of a Traceback

Traceback (most recent call last):
  File "main.py", line 12, in <module>
    result = calculate(data)
  File "main.py", line 7, in calculate
    return sum(values) / len(values)
ZeroDivisionError: division by zero
Enter fullscreen mode Exit fullscreen mode

This traceback has three parts:

Part 1: "Traceback (most recent call last)" tells you the list you are about to read goes from oldest call at the top to newest call at the bottom. The error happened at the bottom.

Part 2: The stack of function calls that led to the error. Each entry shows the file, line number, function name, and the actual line of code that was executing.

Part 3: The exception type and message. This is the most useful line. ZeroDivisionError: division by zero tells you exactly what happened.


The Five Error Types You See Most Often

NameError means you used a name before defining it or spelled it wrong.

NameError: name 'reslt' is not defined
Enter fullscreen mode Exit fullscreen mode

Check your spelling on the line number shown. Look for typos. Check whether the variable was defined in a scope you can access.

TypeError means you applied an operation to the wrong type.

TypeError: can only concatenate str (not "int") to str
Enter fullscreen mode Exit fullscreen mode

You tried to do "hello" + 5. Python will not implicitly convert types. Use "hello" + str(5) or an f-string.

IndexError means you tried to access a list position that does not exist.

IndexError: list index out of range
Enter fullscreen mode Exit fullscreen mode

The list has fewer elements than the index you used. Check your loop bounds and off-by-one logic.

KeyError means you accessed a dictionary key that does not exist.

KeyError: 'username'
Enter fullscreen mode Exit fullscreen mode

The key 'username' is not in the dictionary. Use .get('username') to return None instead of raising, or check if 'username' in my_dict first.

AttributeError means you called a method or accessed an attribute that does not exist on that type.

AttributeError: 'list' object has no attribute 'keys'
Enter fullscreen mode Exit fullscreen mode

You called .keys() on a list. That method only exists on dictionaries. Check what type your variable actually is at that point in the code.


Reading a Multi-Level Traceback

Traceback (most recent call last):
  File "app.py", line 25, in <module>
    run_pipeline(data)
  File "app.py", line 18, in run_pipeline
    cleaned = clean_data(raw)
  File "app.py", line 10, in clean_data
    return [row.strip() for row in data]
  File "app.py", line 10, in <listcomp>
    return [row.strip() for row in data]
AttributeError: 'int' object has no attribute 'strip'
Enter fullscreen mode Exit fullscreen mode

Reading from bottom to top: .strip() was called on an integer, inside a list comprehension on line 10, inside clean_data, called from run_pipeline, called from the main module.

The diagnosis: your data list contains integers mixed in with strings. The clean_data function assumed all elements were strings and called .strip() on all of them.

You do not need Stack Overflow to find this. The traceback told you everything.


The UnboundLocalError: The Most Confusing Python Error

x = 10

def increment():
    x += 1
    return x

print(increment())
Enter fullscreen mode Exit fullscreen mode
UnboundLocalError: local variable 'x' referenced before assignment
Enter fullscreen mode Exit fullscreen mode

This surprises everyone the first time. x exists as a global so why can't the function use it?

Because there is an assignment to x inside the function (x += 1). Python marks any name that appears on the left side of an assignment as local to the entire function, even lines before the assignment.

So when x += 1 tries to read x on the right side first, Python looks for a local x that has not been assigned yet, hence UnboundLocalError.

Fix: add global x before the assignment, or better, pass x as a parameter and return the new value.

Practice reading and predicting Python errors at PyCodeIt.


Top comments (0)