Your program stops and the screen fills with red text. It looks like you've broken something badly. You haven't. That wall of text is called a traceback, and it is Python telling you, as precisely as it can, what went wrong and where. Once you know the reading order, most error messages take about ten seconds to understand.

Every example on this page was produced by actually running the code with Python 3.11. Other versions word a few messages slightly differently and draw the little ^^^ markers differently (versions before 3.11 don't show the ~~~^~~~ markers at all), but the structure is the same everywhere.

An error is a report, not a punishment

When Python hits something it can't do, it can't just guess and carry on, because a wrong guess could quietly produce wrong results. So it stops the program and writes a report. In Python, that "something went wrong" event is called an exception (people say the code raised or threw an exception), and the report it prints is the traceback.

Here's a small shopping program. It has a dictionary of prices (a dictionary stores pairs: a key like "apple" and a value like 0.5), a function that looks up one price, and a function that adds up a whole basket:

prices = {"apple": 0.50, "pear": 0.75}

def price_of(item):
    return prices[item]

def basket_total(items):
    total = 0
    for item in items:
        total += price_of(item)
    return total

print(basket_total(["apple", "Pear"]))

Save it as shop.py, run python3 shop.py, and you get the traceback below. Tap any part of it to see what it means, and watch the source code light up to show which line each part is talking about. Or press Read it in order to walk through it the way experienced programmers do.

Annotated traceback · tap any part

Traceback (most recent call last):
  File "/home/ada/shop.py", line 12, in <module>
    print(basket_total(["apple", "Pear"]))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ada/shop.py", line 9, in basket_total
    total += price_of(item)
             ^^^^^^^^^^^^^^
  File "/home/ada/shop.py", line 4, in price_of
    return prices[item]
           ~~~~~~^^^^^^
KeyError: 'Pear'

shop.py

Tap a highlighted piece of the traceback, or press Read it in order.

Read it from the bottom up

The header says it outright: most recent call last. The newest, most important information is at the bottom. Most beginners read from the top, hit a confusing path, and give up. Flip it around:

  1. The last line: error type and message. KeyError: 'Pear'. The part before the colon is the type of error, a category name. The part after is the message, the specifics. Together: "you asked a dictionary for the key 'Pear' and it doesn't have one".
  2. The block just above it: where it happened. Each block of a traceback is called a frame. It names a file, a line number, a function, and then shows the line of code itself. The bottom frame is the exact line that was running when things went wrong: line 4, return prices[item].
  3. The markers under the code: which part of the line. Since Python 3.11, ^ and ~ point at the exact piece of the line involved. ~~~~~~^^^^^^ under prices[item] says "the lookup [item] on prices".
  4. The frames above: how the program got there. Read upward and you get the story in reverse: price_of was called by basket_total on line 9, which was called from the top of the file on line 12.

The call chain: who called whom

When one function calls another, Python has to remember where to come back to. It keeps a list of "functions currently in progress", called the call stack. The traceback is simply a printout of that stack at the moment of the crash, oldest at the top, newest at the bottom.

The top frame says in <module>. "Module" is Python's word for a file, so <module> means "the top level of the file, not inside any function". That's where your program starts. Every frame below it is one step deeper into a function call.

The crash line isn't always the bug line. Line 4 is perfectly fine code. The real mistake is on line 12: someone typed "Pear" with a capital P, and the dictionary only knows "pear". Python can only tell you where it noticed the problem. Treat the frames as a list of suspects, starting at the bottom and walking up until you find the line where the bad value came from.

In bigger programs, some frames will point into files you didn't write, like Python's own library or a package you installed. Skip those. Look for the lowest frame that's in your own file: that's almost always where you need to start looking.

The five errors you'll meet first

Python has dozens of error types, but as a beginner you'll see these five again and again. Learn what each one usually means and you'll fix most crashes on sight.

SyntaxError "this isn't valid Python"

  File "/home/ada/main.py", line 1
    print("hi"
         ^
SyntaxError: '(' was never closed

Syntax is the grammar of a language. Python reads your whole file before running any of it, and if the grammar is broken it refuses to start. Notice there's no Traceback (most recent call last) header: nothing ran, so there's no call chain. Usual causes: a missing bracket or quote, a missing : after if, for or def, or = where you meant ==. Wrong indentation gives an IndentationError, which is a kind of SyntaxError. One trap: the reported line can be after the real mistake, because Python only realises something is wrong when it reaches a spot that can't make sense. If the line looks fine, check the line above it.

NameError "I don't know that name"

Traceback (most recent call last):
  File "/home/ada/main.py", line 2, in <module>
    print(totl)
          ^^^^
NameError: name 'totl' is not defined. Did you mean: 'total'?

You used a variable or function name that doesn't exist (yet). Nine times out of ten it's a typo, and Python 3.10+ even suggests the name you probably meant. Other causes: different capitals (Print isn't print), using a variable on a line that runs before the line that creates it, or forgetting the quotes around text, so hello is read as a name instead of the string "hello".

TypeError "wrong kind of value for this"

Traceback (most recent call last):
  File "/home/ada/main.py", line 2, in <module>
    print("You are " + age + " years old")
          ~~~~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str

Every value has a type: text is str, whole numbers are int, and so on. A TypeError means you tried an operation that doesn't work for the types involved. Here age is the number 30, and + can't glue text and a number together ("concatenate" means join strings end to end). Fix: "You are " + str(age) + " years old". Calling a function with the wrong number of arguments is a TypeError too: greet() missing 1 required positional argument: 'name'.

IndexError "there's no item at that position"

Traceback (most recent call last):
  File "/home/ada/main.py", line 2, in <module>
    print(colors[3])
          ~~~~~~^^^
IndexError: list index out of range

An index is a position number in a list or string, and Python counts from 0. A list of three colours has positions 0, 1 and 2, so colors[3] asks for a fourth item that isn't there. This "off by one" mistake is extremely common, especially in loops. The list was colors = ["red", "green", "blue"]; the last item is colors[2], or colors[-1] (negative numbers count from the end).

KeyError "that key isn't in the dictionary"

Traceback (most recent call last):
  File "/home/ada/main.py", line 2, in <module>
    print(prices["banana"])
          ~~~~~~^^^^^^^^^^
KeyError: 'banana'

The dictionary's version of IndexError: you asked for a key it doesn't have. The message is just the missing key itself. Check the spelling and the capitals ("Pear" and "pear" are different keys), and check whether the key was ever added. If a missing key is normal in your program, use prices.get("banana"), which gives back None instead of crashing, or prices.get("banana", 0) to pick your own default.

Game: which error is it?

Time to practise. Read each little program and predict which error Python raises. After you pick, you'll see the real output, copied exactly from Python 3.11.

Round 1score 0

  

    

A simple debugging routine

Debugging just means finding and fixing the cause of a problem. When the error isn't obvious, don't start changing random things and hoping. Follow the same calm routine every time:

  1. Read the last line. Error type plus message. Say it in plain words: "the dictionary has no key 'Pear'".
  2. Find the lowest frame in your own code and open that line in your editor.
  3. Reproduce it. Make the error happen again, on purpose, every time you run. If it only happens sometimes, find the input that triggers it. Shrink the program or the input until it's as small as possible and still fails.
  4. Print the values. Right before the line that crashes, print the variables it uses. Your assumption about what's in them is usually the thing that's wrong.
  5. Change one thing, then run again. Make one small change that tests your guess. If you change three things at once and it works, you won't know which one fixed it, and you might have broken something else.
  6. Still stuck? Search the last line. Copy the error type and message, remove your own names (like 'Pear'), and search for it. Thousands of people have hit the same message before you.

Here's step 4 on the shop program. Add one line to price_of:

def price_of(item):
    print("looking up:", item)
    return prices[item]

Run it again and the output starts:

looking up: apple
looking up: Pear
Traceback (most recent call last):
  ...
KeyError: 'Pear'

The first lookup worked; the second one, with a capital P, crashed. Now the cause is obvious. Fix the data on line 12 ("pear"), or make the lookup forgiving with prices[item.lower()], which turns "Pear" into "pear" first. Either way the program prints 1.25. Then remove the debugging print again.

Check yourself

A long traceback appears. Which part should you read first?

The last line holds the error type and message. The header itself says it: most recent call last.

A traceback has three frames: in <module>, then in load, then in parse. Which function was running when the error happened?

The bottom frame is the newest call. The top level called load, load called parse, and parse is where it went wrong. (The real mistake might still be higher up, in the value load passed in.)

Your program prints some output, then crashes with a SyntaxError. Is that possible?

Python checks the grammar of the whole file before running any of it, so a SyntaxError in the file you run stops it before the first line. (A SyntaxError can only show up mid-run when your program loads code from somewhere else, such as another file it imports.)

names = ["Ana", "Bo"] then print(names[2]). What happens?

Two items have positions 0 and 1. Position 2 doesn't exist, and lists raise IndexError. KeyError is for dictionaries.

The short version

Next time the red text appears, skip straight to the bottom. The answer is usually sitting right there.