Debugging: Reading Error Messages and Fixing Bugs

What you’ll learn in this lesson

  • Why error messages are help, not failure
  • How to read an error message from the bottom up
  • The seven errors beginners meet most, and what each one means
  • A four-step routine that works on any bug
  • How to find bugs that give no error at all, using print()

Every programmer meets bugs

A bug is a mistake in a program. Every programmer, beginner or expert, writes bugs every day. What separates beginners from experienced programmers is not fewer bugs. It is knowing what to do next.

Bugs come in two kinds. Some stop the program with an error message. Those are the friendly ones, because Python tells you what went wrong and where. Others run without any error but give the wrong answer. Those take a little detective work, and you will learn that too.

The habit to build today: when you see red text, don’t panic and don’t guess. Read it.


Reading an error message

Here is a program with a typo, and what Python says when you run it:

score = 5
print(scroe)
Traceback (most recent call last):
  File "C:\python-course\bug1.py", line 2, in <module>
    print(scroe)
          ^^^^^
NameError: name 'scroe' is not defined. Did you mean: 'score'?

That looks like a lot, but you only need two parts, and you read them from the bottom up:

  1. The last line says what went wrong. NameError is the kind of error, and the rest explains it: Python has never heard of a name called scroe.
  2. The lines above it say where. line 2 tells you which line of your file, and the line of code is shown right under it.

Start at the bottom, then find the line number. Everything else in the message can be ignored for now. Your message may look slightly different from this one, because the underline marks and the “Did you mean” hint depend on your version of Python. The last line and the line number are always there.


The seven most common errors

1. SyntaxError: Python can’t read what you wrote

A SyntaxError means the code is broken like a sentence with a missing word. The usual causes are a missing colon, a missing closing quote or parenthesis, or a mix-up between = and ==.

age = 12
if age >= 10
    print("Old enough")
  File "bug.py", line 2
    if age >= 10
                ^
SyntaxError: expected ':'

Every if, elif, else, for and while line ends with a colon. Add it and the error is gone.

An unclosed parenthesis looks like this:

print("Hello"
print("World")
  File "bug.py", line 1
    print("Hello"
         ^
SyntaxError: '(' was never closed

And here is the classic mix-up from the Booleans lesson, = where you meant ==:

age = 12
if age = 12:
    print("Twelve")
  File "bug.py", line 2
    if age = 12:
       ^^^^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

In Python this is an error, not a silent bug, so Python stops you. Use == to ask a question.

Tip: Python reads the whole file before running any of it, so a SyntaxError appears before anything prints. If the line it points to looks fine, check the line above it. The real mistake is often just before.

2. IndentationError: the spaces are wrong

age = 12
if age >= 10:
print("Old enough")
  File "bug.py", line 3
    print("Old enough")
    ^
IndentationError: expected an indented block after 'if' statement on line 2

The line after a colon must be indented, usually four spaces. Indent it and run again.

3. NameError: Python doesn’t know that name

print(Hello)
NameError: name 'Hello' is not defined

Three causes cover almost every NameError: a typo in a variable name (scroe for score), forgetting the quotes around text (Hello instead of "Hello"), or using a name before you created it. Capital letters count, so true instead of True gives this error too.

4. TypeError: the wrong kinds of things together

print("Age: " + 12)
TypeError: can only concatenate str (not "int") to str

You tried to join text and a number with +. Show them with a comma instead, print("Age:", 12), or convert the number with str(). This is also what you get when you forget int() on an answer from input().

5. IndexError: that position doesn’t exist

fruits = ["apple", "banana", "cherry"]
print(fruits[3])
IndexError: list index out of range

The list has three items, at positions 0, 1 and 2. There is no position 3. Remember that counting starts at 0, so the last position is one less than len().

6. KeyError: that label doesn’t exist

student = {"name": "Mia"}
print(student["age"])
KeyError: 'age'

The dictionary has no entry labeled age. Check your spelling, and check that the entry was added before you read it.

7. ValueError: right kind of thing, wrong value

age = int("twelve")
ValueError: invalid literal for int() with base 10: 'twelve'

int() can only convert text that looks like a whole number. twelve and 12.5 both fail.

Error cheat sheet

Error It usually means Check first
SyntaxError Python can’t read the code Colon, quotes, parentheses, = vs ==
IndentationError Spaces are wrong Indent the line after a colon
NameError Python doesn’t know the name Typos, missing quotes, capital letters
TypeError Wrong kinds of things together Text plus a number
IndexError List position doesn’t exist Counting from 0, len()
KeyError Dictionary label doesn’t exist Spelling of the key
ValueError Right type, wrong value Does the text look like a number?

You will meet others, such as ZeroDivisionError when you divide by zero (10 / 0). The method for handling them is exactly the same.


A four-step routine for any bug

  1. Read the last line. It names the error and says what went wrong.
  2. Go to the line number. Look at that line, and the line above it.
  3. Say what you expected and what happened. Out loud is best. “I expected it to print 15, but it printed 20.”
  4. Change one thing, then run it again. One change at a time, so you always know which change helped.

The fourth step matters most. If you change five things at once and the bug disappears, you won’t know why, and if it gets worse, you won’t know which change did it.


Bugs with no error message

The hardest bugs run perfectly and give the wrong answer. Python can’t warn you, because it did exactly what you asked. It just wasn’t what you meant.

a = 10
b = 20
average = a + b / 2
print(average)
20.0

You expected 15.0, the average of 10 and 20, and got 20.0. There is no error to read, so you have to look inside the program.

print() is your flashlight. Add a line that shows what a value actually is, run the program, and compare it with what you expected:

total = 0
for number in range(1, 4):
    total = total + number
    print("number is", number, "total is", total)
print(total)
number is 1 total is 1
number is 2 total is 3
number is 3 total is 6
6

Each line shows the program’s thinking at that moment. When a value is not what you expected, you have found where the bug starts. For the average bug, the cause is the order of operations from the Numbers lesson: division happens before addition, so b / 2 ran first. Parentheses fix it:

average = (a + b) / 2

Once the bug is fixed, delete the extra print() lines.


When you’re stuck

  • Read your code aloud, line by line, as if explaining it to someone who knows nothing. You will often hear the mistake as you say it.
  • Shrink the problem. Copy the smallest piece that still goes wrong into a new file and test that.
  • Copy the last line of the error message into a search engine. Thousands of people have hit the same one.
  • Take a short break. Fresh eyes spot a missing colon in seconds.
  • Go back to the last version that worked, then make changes one at a time from there.

Debugging: Reading Error Messages and Fixing Bugs

Python for Absolute Beginners ยท Lesson 14

1 / 21

What you'll learn

  • Why error messages are help, not failure
  • How to read an error message from the bottom up
  • The seven errors beginners meet most, and what each one means
  • A four-step routine that works on any bug
  • How to find bugs that give no error at all, using print()
2 / 21

Every programmer meets bugs

  • A bug is a mistake in a program
  • Every programmer, beginner or expert, writes bugs every day
  • Some bugs stop the program with an error message
  • Others run, but give the wrong answer
  • When you see red text, don't panic and don't guess: read it
3 / 21

Reading an error message

score = 5
print(scroe)

Output:
Traceback (most recent call last):
  File "C:\python-course\bug1.py", line 2, in <module>
    print(scroe)
          ^^^^^
NameError: name 'scroe' is not defined. Did you mean: 'score'?
4 / 21

Read it from the bottom up

  • The last line says what went wrong: a NameError, Python doesn't know the name scroe
  • The lines above say where: line 2, and the line of code
  • Start at the bottom, then find the line number
  • Your message may look slightly different, depending on your version of Python
5 / 21

SyntaxError: the missing colon

age = 12
if age >= 10
    print("Old enough")

Output:
SyntaxError: expected ':'
  • Every if, elif, else, for and while line ends with a colon
  • Python reads the whole file first, so a SyntaxError appears before anything prints
  • If the line it points to looks fine, check the line above
6 / 21

SyntaxError: parentheses and = versus ==

print("Hello"

Output:
SyntaxError: '(' was never closed

if age = 12:

Output:
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
  • Every opening parenthesis needs a closing one
  • One = stores a value. Two == ask a question
  • In an if line, use ==
7 / 21

IndentationError

age = 12
if age >= 10:
print("Old enough")

Output:
IndentationError: expected an indented block after 'if' statement on line 2
  • The line after a colon must be indented, usually four spaces
8 / 21

NameError

print(Hello)

Output:
NameError: name 'Hello' is not defined
  • A typo in a variable name
  • Forgetting the quotes around text
  • Using a name before you created it
  • Capital letters count: true is not True
9 / 21

TypeError

print("Age: " + 12)

Output:
TypeError: can only concatenate str (not "int") to str
  • You tried to join text and a number with +
  • Use a comma instead: print("Age:", 12)
  • Or convert the number with str()
  • Also what you get when you forget int() on an answer from input()
10 / 21

IndexError and KeyError

fruits = ["apple", "banana", "cherry"]
print(fruits[3])

Output:
IndexError: list index out of range

student = {"name": "Mia"}
print(student["age"])

Output:
KeyError: 'age'
  • Positions start at 0, so the last position is one less than len()
  • Check the spelling of dictionary keys, and that the entry was added first
11 / 21

ValueError

age = int("twelve")

Output:
ValueError: invalid literal for int() with base 10: 'twelve'
  • int() can only convert text that looks like a whole number
  • "twelve" and "12.5" both fail
12 / 21

Error cheat sheet

ErrorIt usually meansCheck first
SyntaxErrorPython can't read the codeCheck colon, quotes, parentheses, = vs ==
IndentationErrorThe spaces are wrongIndent the line after a colon
NameErrorPython doesn't know the nameCheck typos, quotes, capital letters
TypeErrorWrong kinds of things togetherText plus a number?
IndexErrorThat list position doesn't existCount from 0
KeyErrorThat dictionary label doesn't existCheck the spelling
ValueErrorRight type, wrong valueDoes the text look like a number?
13 / 21

A four-step routine

  1. Read the last line
  2. Go to the line number, and look at the line above it
  3. Say what you expected and what happened
  4. Change one thing, then run it again

One change at a time, so you always know which change helped

14 / 21

Bugs with no error message

a = 10
b = 20
average = a + b / 2
print(average)

Output:
20.0
  • Expected 15.0, got 20.0
  • Python did exactly what you asked, just not what you meant
  • No error to read, so look inside the program
15 / 21

print() is your flashlight

total = 0
for number in range(1, 4):
    total = total + number
    print("number is", number, "total is", total)
print(total)

Output:
number is 1 total is 1
number is 2 total is 3
number is 3 total is 6
6
  • Show what a value really is, then compare it with what you expected
  • The average bug: division happens first. The fix: average = (a + b) / 2
  • Delete the extra print() lines once the bug is fixed
16 / 21

When you're stuck

  • Read your code aloud, line by line
  • Shrink the problem: test the smallest piece that still goes wrong
  • Search the last line of the error message
  • Take a short break
  • Go back to the last version that worked, then change one thing at a time
17 / 21

Hands-on exercise

  • Make each of the seven errors on purpose, and write down each last line in your own words
  • Run the practice file and fix its three bugs, one at a time
  • Fix the average program so it prints 15.0
  • Add print() lines inside a loop you wrote earlier, then remove them
  • Write the four-step routine on a sticky note
18 / 21

Key takeaways

  • An error message is Python helping you: read it
  • Read from the bottom up: the last line says what, the line number says where
  • The seven common errors: SyntaxError, IndentationError, NameError, TypeError, IndexError, KeyError, ValueError
  • Four steps fix any bug: read the last line, go to the line, say what you expected, change one thing
  • No error but the wrong answer? Use print() to look inside
19 / 21

Take the quiz

Take the Lesson 14 quiz: 5 quick questions to check what you learned.

20 / 21

Next lesson

Functions: Reusable Blocks

21 / 21

Press play on any slide and the lesson plays on by itself from there. You can still click Next or click a slide to move on.

Download the Lesson 14 slides (PowerPoint, with narration)

Download the Lesson 14 slides (PDF)

Hands-on exercise

  1. Make each of the seven errors on purpose, using the examples in this lesson. Write down each last line in your own words.
  2. Run the practice file below. Before you fix each bug, write down the last line of the error and what you think it means.
  3. This program should print 15.0 but prints 20.0. Find the bug and fix it:
    a = 10
    b = 20
    average = a + b / 2
    print(average)
  4. Take any program you wrote earlier and add print() lines inside its loop to show the values at each step. Then remove them.
  5. Write the four-step routine in your own words on a sticky note, and keep it near your computer.

Practice file

Save this as lesson14-practice.py and run it with F5 in IDLE. On a Mac, if F5 does nothing, use Run, then Run Module, from the menu.

# Lesson 14: Debugging practice: three bugs
# WHAT TO DO: This program should add up three scores and print their
# total and average. It has three bugs, one at a time. Run it, read the
# error message from the bottom up, fix that one bug, then run it again.
# Each fix reveals the next bug.
# HINT: the bugs are a SyntaxError, a NameError, and a TypeError.
# Run with F5 in IDLE. You are done when it prints exactly:
#     Total: 245
#     Average: 81.66666666666667

scores = [80, 95, 70]
total = 0
for score in scores
    total = total + score
print("Total:", totl)
average = total / len(scores)
print("Average: " + average)

Key takeaways

  • An error message is Python helping you. Read it instead of fearing it.
  • Read from the bottom up: the last line says what went wrong, and the line number says where.
  • The seven common errors are SyntaxError, IndentationError, NameError, TypeError, IndexError, KeyError and ValueError.
  • Four steps work on any bug: read the last line, go to the line, say what you expected, change one thing.
  • A program that runs but gives the wrong answer has a logic bug. Use print() to look inside it.
  • When you're stuck, read the code aloud, shrink the problem, search the error, or take a break.

Next lesson: Functions: Reusable Blocks.