How to read a traceback
A traceback is the wall of text Python prints when something goes wrong. Most beginners glance at it, feel a small wave of dread, and scroll back to their code to guess. That is the expensive habit this lesson removes.
A traceback is not a complaint. It is a report telling you what went wrong, where, and how the program got there — usually enough to fix the problem without looking at anything else.
A simple one
numbers = [1, 2, 3]
print(numbers[5])
Traceback (most recent call last):
File "/home/priya/app.py", line 2, in <module>
print(numbers[5])
~~~~~~~^^^
IndexError: list index out of range
Four pieces of information, and you read them from the bottom.
IndexError: list index out of range — the last line is the actual problem.
Error type, then a message. Read this first, always.
print(numbers[5]) — the line that failed, quoted back at you.
~~~~~~~^^^ — Python 3.11 and later point at the exact part of the line
that broke. On a line with several operations this is genuinely valuable.
File "/home/priya/app.py", line 2 — where.
So: something asked for a list index that does not exist, on line 2, in
numbers[5]. You now know the fix without re-reading anything.
Why it is called a traceback
Errors usually happen several calls deep:
def get_average(numbers):
return sum(numbers) / len(numbers)
def report(data):
average = get_average(data)
print(f"Average: {average}")
report([])
Traceback (most recent call last):
File "/home/priya/app.py", line 8, in <module>
report([])
File "/home/priya/app.py", line 5, in report
average = get_average(data)
File "/home/priya/app.py", line 2, in get_average
return sum(numbers) / len(numbers)
~~~~~~~~~~~~~^~~~~~~~~~~~~~
ZeroDivisionError: division by zero
That is the call stack — the path Python took to reach the failure, oldest first.
- Line 8 called
report([]) - which on line 5 called
get_average(data) - which on line 2 divided by zero
"Most recent call last" is the important phrase. The bottom frame is where it broke. The frames above tell you how you got there.
Where the bug actually is
The error happened in get_average. The bug might not be.
get_average is arguably fine — dividing by the length of an empty list is a
reasonable thing to fail on. The real question is why report was called with
an empty list, and the traceback hands you that: line 8.
Read from the bottom to find where it broke. Read upwards to find why. That second half is the part beginners skip, and it is where most real bugs live.
Reading your own frames first
In a real project the stack includes library code:
Traceback (most recent call last):
File "/home/priya/app.py", line 42, in <module>
response = requests.get(url)
File "/usr/lib/python3/requests/api.py", line 73, in get
return request("get", url, params=params, **kwargs)
File "/usr/lib/python3/requests/sessions.py", line 529, in request
prep = self.prepare_request(req)
...
MissingSchema: Invalid URL 'example.com': No scheme supplied.
Twenty frames, eighteen of them inside requests. The library is almost
certainly not broken.
Scan for the last line that mentions a file you wrote. Here that is line 42
of app.py, and the message confirms it: the URL needed https://. The
intervening frames are how the library discovered your mistake, not evidence of
its own.
The two-part error line
ValueError: invalid literal for int() with base 10: 'abc'
The type before the colon tells you the category, and each has a consistent meaning:
ValueError— right type, unusable valueTypeError— wrong type entirelyKeyError— that key is not in that dictionaryIndexError— that position is not in that sequenceAttributeError— that object has no such method or attributeNameError— that name has not been definedZeroDivisionError— self-explanatory
Recognising the type usually narrows the cause before you read anything else. The next lesson goes through them properly.
The message after the colon is the specific detail. Note that this one
quotes the offending value — 'abc'. Error messages often contain the actual
data that broke, which saves you adding a print to find out.
"During handling of the above exception"
Sometimes you get two tracebacks joined:
Traceback (most recent call last):
File "app.py", line 3, in <module>
value = data["count"]
KeyError: 'count'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "app.py", line 5, in <module>
print(f"Count: {count}")
NameError: name 'count' is not defined
Read the first one. The second happened while dealing with the first and is usually a consequence. Fix the top, and the bottom often disappears.
You will also see "The above exception was the direct cause of the following
exception", which means the same thing more deliberately — code caught one error
and raised another. That is raise ... from ..., in the raising lesson.
Tracebacks in a loop
When the same error appears a thousand times, scroll to the first. The ones after it are frequently caused by the first leaving something in a bad state.
Making them useful to future you
Two habits pay off immediately.
Do not screenshot a traceback — copy the text. You can search it, and the exact wording is what a search engine or a colleague needs.
When asking for help, include the whole thing. "I get a KeyError" is
almost unanswerable. The full traceback contains the file, the line, the call
path and the offending key.
Practice
For each, trigger the error deliberately, read the traceback aloud, and say which line is the cause rather than the site of the failure.
-
print([1, 2, 3][10]) -
print(int("abc")) -
print({"a": 1}["b"]) -
print("5" + 5) -
print(undefined_variable) -
print("hello".push("x")) -
Write the three-function
report([])example. Identify which frame is the failure and which is the bug. -
Write a function calling a function calling a function, with the innermost failing. Count the frames and confirm the order.
-
Take a traceback from question 7 and write down, in one sentence each: what broke, where, and why it was called that way.
-
Cause an error inside a
forloop running ten times. Notice the program stops at the first one — Python does not carry on and collect the rest.
Next: the specific errors you will meet most, and what each one usually means in practice.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship