Read a Python error message¶
Beginner-friendly · 12 min · real Python 3.12 messages
A red wall of text looks scary, but a Python error (a traceback) is a map that tells you what went wrong and where. Learn to read it in the right order and most bugs take minutes, not hours.
The 3-step method¶
Here's a real traceback. Our app.py calls build_prompt() from helpers.py:
Traceback (most recent call last):
File "C:\project\app.py", line 8, in <module>
main()
File "C:\project\app.py", line 5, in main
prompt = build_prompt(doc)
^^^^^^^^^^^^^^^^^
File "C:\project\helpers.py", line 2, in build_prompt
return "Summarise: " + doc["text"]
~~~^^^^^^^^
KeyError: 'text'
Step 1 — Read the LAST line first. It says what happened:
KeyError: 'text' → "I looked for the key 'text' in a dictionary and it isn't there."
Step 2 — Read upwards to find the line that broke. The lowest File … line is where Python
stopped: helpers.py, line 2, doc["text"]. The ~~~^^^^ marks the exact part.
Step 3 — Keep reading up to see how you got there. app.py line 5 passed doc into
build_prompt(). So the question becomes "what's in doc?":
Fix: use the right key — doc["body"] — or doc.get("text", "") if the key is optional.
The order to read a traceback
Bottom line (what) → lowest line in your file (where) → lines above (how you got there).
Lines from inside libraries (site-packages\…) are rarely the bug — find the last line that's
your code.
flowchart BT
E["KeyError: 'text'<br/><b>1. What happened</b>"] --> W["helpers.py, line 2<br/><b>2. Where it broke</b>"]
W --> H["app.py, line 5 → line 8<br/><b>3. How you got there</b>"]
The 15 errors you'll see most¶
Errors in the code itself (Python can't even start)¶
| Error | What it means | Usual fix |
|---|---|---|
SyntaxError: '[' was never closed |
A bracket, quote or parenthesis isn't closed | Look at the line shown and the line before it |
IndentationError: expected an indented block after function definition on line 1 |
The body of a def / if / for isn't indented |
Indent the block with 4 spaces |
SyntaxError: expected ':' (or just invalid syntax) |
A missing : — or something else Python can't parse |
Check for : after if, for, def, class; look for typos near the ^ |
Names and attributes¶
| Error | What it means | Usual fix |
|---|---|---|
NameError: name 'prnt' is not defined. Did you mean: 'print'? |
A typo, or a variable used before it's created | Python 3.12 often suggests the fix — read it! |
AttributeError: 'NoneType' object has no attribute 'upper' |
The value is None — usually a function that forgot to return |
Find where the variable was set; check that function returns something |
AttributeError: 'str' object has no attribute 'uppercase' |
That method doesn't exist on this type | Check the right name (.upper()) with dir(value) |
UnboundLocalError: cannot access local variable 'total' … |
You assign to a variable inside a function that also exists outside | Pass it in and return the new value instead |
Wrong values and types¶
| Error | What it means | Usual fix |
|---|---|---|
TypeError: can only concatenate str (not "int") to str |
Mixing text and numbers with + |
f"Total: {count}" or str(count) |
TypeError: f() takes 1 positional argument but 2 were given |
Called a function with the wrong number of arguments | Compare the call with the def line (in a class, remember self) |
TypeError: object of type 'int' has no len() |
Called something on the wrong type | print(type(x)) to see what you really have |
ValueError: invalid literal for int() with base 10: '12a' |
Right type, bad content | Clean or validate the input first |
Data, files and packages¶
| Error | What it means | Usual fix |
|---|---|---|
KeyError: 'nme' |
Dictionary key doesn't exist | Check spelling; d.get("key") for optional keys; print(d.keys()) |
IndexError: list index out of range |
Asked for item 5 of a 2-item list | Check len(items); is the list empty? |
FileNotFoundError: [Errno 2] No such file or directory: 'missing.txt' |
Wrong path — or run from a different folder | Use Path(__file__).parent / "missing.txt" |
ModuleNotFoundError: No module named 'openia' |
Typo, package not installed, or wrong virtual environment | Check spelling → pip install → check which python / where python |
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Very common in GenAI code: the LLM (or API) didn't return pure JSON — often it added text like "Sure! Here's the JSON". Print the raw text before parsing it. See Handle LLM API errors.
When the message isn't enough¶
1. Print the value and its type, right before the failing line
doc = {"title": "Refund policy", "body": "Refunds within 30 days."}
print(f"{type(doc)=} {doc.keys()=}")
# → type(doc)=<class 'dict'> doc.keys()=dict_keys(['title', 'body'])
The = inside an f-string prints both the expression and its value — perfect for debugging.
2. Pause the program and look around — add breakpoint() on the line before the error and
run the file. You get a prompt where you can type variable names:
(Pdb) doc ← print a variable
(Pdb) n ← run the next line
(Pdb) c ← continue to the end
(Pdb) q ← quit
In VS Code, click left of a line number to set a red breakpoint and press F5 — see VS Code shortcuts.
3. Search smart — copy the last line of the traceback, remove your own names and paths,
and search for that. For example, search
AttributeError: 'NoneType' object has no attribute, not my_bot.py line 42.
4. Ask an AI assistant well — paste the whole traceback and the code it points to, plus what you expected to happen. "It doesn't work" gets a guess; the traceback gets an answer.
Practice¶
Read each error and say what's wrong before opening the answer.
1. AttributeError: 'NoneType' object has no attribute 'strip' on text = load(path).strip()
load() returned None — probably it has no return statement, or it returns nothing when the
file is empty. Fix the function so it always returns a string.
2. ModuleNotFoundError: No module named 'openai' — but you did pip install openai
You installed it into a different Python than the one running your file. Activate your virtual environment (or select the interpreter in VS Code) and install again there.
3. TypeError: ask() takes 1 positional argument but 2 were given on bot.ask(\"hi\")
ask is a method in a class but was defined as def ask(question): — methods need self first:
def ask(self, question):.