Topic 0.7
Reading Error Messages and Tracebacks
In one line
When Python cannot run a line it stops and prints an error message. Read it from the bottom: the last line names the kind of error and what went wrong, and the lines above it (the traceback) show the file and line number where it happened.
Think of it like this
A parcel that could not be delivered. The courier does not just give up silently; a note says what went wrong ("house number not found") and where ("at step 3: Gandhi Road"). A Python error message is that note. It tells you what went wrong and where, and it is there to help you.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Error
- Python's report that it could not do what the code asked.
- Syntax error
- A grammar mistake found before the program starts running.
- Exception
- An error that happens while the program is running.
- Traceback
- The report printed for an exception: the chain of lines that led to the error, ending with the error itself.
- Error type
- The category name at the start of the last line, such as
TypeErrororNameError. - Raise
- What Python does when an error happens: it "raises" an exception, which stops the program unless something handles it.
- Crash
- A program stopping because of an error nobody handled.
- Call
- To run a named group of code (a function).
print("hi")callsprint. - Name
- The label that stands for a value, such as
countorprint. Topic 1.1 teaches names and variables.
Step by step
01An error stops the program where it happens
This program has four lines. The third uses a name that doesn't exist. Lines 1 and 2 run and print; line 3 fails; line 4 never runs.
The traceback appears after the normal output, because the output had already been printed when the error happened.
print("Line 1 runs")
print("Line 2 runs")
print(undefined_name)
print("Line 4 never runs")02Read it from the bottom
Last line: NameError: name 'undefined_name' is not defined. The type is NameError; the message says which name. That alone usually tells you the fix.
Above it: File "main.py", line 3 gives the file and the line number. Then comes the line of code, and the ^ marks sit under the exact part Python could not handle. in <module> means the line is at the top level of the file, not inside a function.
03A syntax error: nothing runs
Here the first line would print fine, but the second has no closing quote. Python checks the grammar of the whole file before running any of it, so even Step 1 is never printed.
A syntax error has no Traceback header, because the program never started and there is no journey to trace. You get the file, the line, a ^ pointing at the spot, and the message.
print("Step 1")
message = "Hello
print(message)04TypeError: the wrong kind of value
+ can add two numbers or join two pieces of text, but it will not join text to a number. The message says exactly that: it can only concatenate (join) str (text) to str, not int (a whole number).
The ~ marks underline the whole expression and the ^ marks the operator in the middle of it. The fix is to turn the number into text with str(count), or to give print the two values separated by a comma.
count = 3
print("Count: " + count)05A traceback with several steps
Real programs group code into functions (Phase 5): named blocks that call each other. You don't need to write one yet. def average(marks): makes a function named average, return hands its answer back, and sum and len are ready-made functions that add up the values and count them. Below, the last line of the file calls report, which calls average, which divides by zero when the list of marks is empty.
The traceback shows all three places, in the order they were called. Read the bottom entry first: line 3, inside average, dividing by len(marks). Then read upward to find out who called it with an empty list: line 9. The bottom shows where it broke; the lines above show how the program got there.
def average(marks):
total = sum(marks)
return total / len(marks)
def report(name, marks):
print(name, "average:", average(marks))
report("Asha", [70, 80])
report("Ravi", [])06The mistake may be one line up
Python reports the place where the code stopped making sense, which can be after the real mistake. Here the bracket is left open on line 1. Modern Python is good at this case and points back at the bracket, but with other mistakes it reports the following line.
Rule of thumb for a SyntaxError: look at the reported line, and if it looks fine, look at the line above.
total = (10 + 20
print(total)07A method for every error
1. Read the last line: type and message. 2. Go to the line number. 3. Look at what the ^ marks point to. 4. Ask what you expected that line to do. 5. Change one thing and run again.
If the message itself is unclear, search for the type and the fixed part of the message (TypeError: can only concatenate str), without your own variable names. AI assistants are good at explaining an error too: paste the whole traceback and the code, and then check that you understand the explanation, because the goal is to recognise the error yourself next time.
Try it yourself
- 1
Fix the NameError two ways
In the first example, fix line 3 by adding quotes:
print("undefined_name"). Run it. Then undo that and instead add a new line above it:undefined_name = 42. Run again. Both fixes work; they mean different things. - 2
Cause three errors on purpose
In the first example, replace line 3 with each of these in turn and read only the last line of each error:
print(10 / 0), thenprint(int("twelve")), thenprint("Total: " + 5). Match each to a row of the table. - 3
Trace the journey
In the third example, change the last line to
report("Ravi", [50])and run it. No error now. Then put the empty list back and addprint("Checking", name)as the first line insidereport. Use the output to say which call fails.
Code & diagrams
The output shows two printed lines and then the traceback. Fix line 3 by putting quotes around the name, or by defining it first.
Expected output
Line 1 runs
Line 2 runs
Traceback (most recent call last):
File "main.py", line 3, in <module>
print(undefined_name)
^^^^^^^^^^^^^^
NameError: name 'undefined_name' is not definedStep 1 is not printed, although its line is correct. Python checks the whole file's grammar first. Add the missing quote.
Expected output
File "main.py", line 2
message = "Hello
^
SyntaxError: unterminated string literal (detected at line 2)Read the traceback from the bottom. Which line broke? Which line called it with an empty list? (def creates a named block of code; Phase 5 teaches it.)
Expected output
Asha average: 75.0
Traceback (most recent call last):
File "main.py", line 9, in <module>
report("Ravi", [])
~~~~~~^^^^^^^^^^^^
File "main.py", line 6, in report
print(name, "average:", average(marks))
~~~~~~~^^^^^^^
File "main.py", line 3, in average
return total / len(marks)
~~~~~~^~~~~~~~~~~~
ZeroDivisionError: division by zeroError type Usually means Example that causes it
SyntaxError broken grammar: bracket, quote or colon print("hi"
IndentationError wrong spaces at the start of a line an indented line with no colon above it
NameError a name Python doesn't know (spelling?) Print("hi") or print(nmae)
TypeError wrong kind of value for this operation "Count: " + 3
ValueError right kind of value, but unusable int("twelve")
IndexError position beyond the end of a list prices[3] when there are 3 prices
KeyError a dictionary has no such key user["age"] when only "name" exists
AttributeError this kind of value has no such feature "hello".push("!")
ZeroDivisionError dividing by zero 10 / 0
ModuleNotFoundError import of a library that isn't there import statisticBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Join text and a number
Build a sentence by adding a number to text with +.
age = 12
print("Next year you will be " + age + 1)Break #2
Ask a list for an item it doesn't have
Make a list of three prices and ask for the item at position 3.
prices = [30, 12, 8]
print(prices[3])Break #3
Convert text that isn't a number
Ask int() to turn the word twelve into a number.
print("Step 1 done")
number = int("twelve")
print("Step 2 done")Myth vs fact
Myth
An error message means I am bad at programming.
Fact
Every programmer sees errors all day. The message is information, and reading it calmly is the professional skill.
Myth
The line number always points at my mistake.
Fact
It points at where Python noticed a problem. The cause can be a line earlier, especially a missing bracket or quote, or in the code that called this line with bad values.
Myth
Long tracebacks are worse than short ones.
Fact
A long traceback is a more detailed map. The last line still says what went wrong; the rest shows the route, which is exactly what you need in a big program.
Myth
If I get an error, I should rewrite the whole thing.
Fact
Change one thing at a time, guided by the message. Rewriting hides what the problem was, and you will meet it again.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The
~and^position markers come from PEP 657 (Python 3.11), which stores column offsets for every bytecode instruction. They are invaluable on lines such asa[i][j] + b[k], where older versions could not say which subscript failed. - ▸
Since 3.10 the parser produces far more specific syntax messages (
'(' was never closed,expected ':'), andNameError/AttributeErrorsuggest close matches. If your errors look vaguer than the ones in this course, you are on an old Python. - ▸
In production, uncaught exceptions should be logged with their full traceback (
logging.exception, Topic 7.9) and usually sent to an error tracker. The traceback is the most valuable debugging artefact you have; never replace it with a bare "something went wrong". - ▸
Exceptions can be chained: "During handling of the above exception, another exception occurred" and "The above exception was the direct cause" join two tracebacks. Read the first one to find the root cause (Topic 7.2).
Remember this
- 1
There are two moments an error can appear. A syntax error is found before the program starts: Python reads the whole file first, and if the grammar is broken anywhere, nothing runs at all. An exception happens while the program runs: every line before the failing one has already run, and the lines after it never do.
- 2
The text Python prints for an exception is a traceback. Read it from the bottom up. The last line has the error's type (such as
NameError) and a message explaining it. Just above are the file name, the line number and the line of code itself, often with^or~marks under the exact part that failed. - 3
When one piece of code calls another, the traceback lists every step of the journey, in the order the calls were made, with the place where the error actually happened last. That is what "most recent call last" means in the first line.
- 4
A handful of error types cover most beginner mistakes. **
SyntaxError: broken grammar, such as a missing bracket or quote.IndentationError: wrong spaces at the start of a line.NameError: a name Python doesn't know, usually a spelling mistake.TypeError: the wrong kind of value, such as adding text to a number.ValueError**: the right kind of value but an unusable one, such asint("twelve"). **IndexErrorandKeyError: asking a list (a row of values, Phase 4) or a dictionary (values looked up by a label, Phase 4) for something that isn't there.ZeroDivisionError**: dividing by zero. - 5
The line Python points at is where it noticed the problem, which is not always where the mistake is. With syntax errors in particular, a missing bracket or quote is often on the line above the one reported.
- 6
Reading errors is a skill, and it is the one that most separates people who get stuck from people who keep moving. The method is always the same: read the last line, go to the line number, compare what the code says with what you meant, change one thing, run again.
Explain it without notes
What is the difference between a syntax error and an exception?
In what order should you read a traceback, and what does each part tell you?
What does "most recent call last" mean?
Give the likely cause of each: NameError, TypeError, IndexError.
Why might the mistake not be on the line that the error reports?
Practice
This program should print Total: 50 but crashes. Read the error, then fix it: line 1 price = 25, line 2 total = price * 2, line 3 print("Total: " + total).
Without running it, say what this prints, including the error type: line 1 print("A"), line 2 print(10 / 0), line 3 print("B").
A program fails with NameError: name 'totl' is not defined. Did you mean: 'total'? on line 7. What is the most likely mistake, and how do you fix it?
Trade-offs
- ↔
Stopping at the first error vs carrying on. Python stops immediately, which can feel harsh but keeps a wrong value from spreading into later results. Languages or tools that carry on silently are harder to debug.
- ↔
Detailed vs short messages. Long tracebacks take practice to read, but each line answers a real question. Hiding them from developers makes problems slower to fix; hiding them from end users (while logging them) is good practice.
Done when you can
Done when you read the last line of an error first, without being told.
Done when you can find the file, line number and position marks in a traceback.
Done when you can explain why a syntax error stops every line from running.
Done when you can name the likely cause of NameError, TypeError, ValueError and IndexError.
Done when you can follow a three-step traceback from the failing line back to the call that caused it.