Reading Error Messages in Python

💡 Big Idea

An error message is not a failure — it is Python telling you exactly what went wrong and where. Most beginners see a wall of red text and panic. Experienced programmers see the same text and immediately know where to look. The difference is not talent — it is knowing how to read what Python is telling you. This article teaches you to do exactly that.

1   Errors Are a Normal Part of Programming

Every programmer — from complete beginner to senior engineer with twenty years of experience — writes code that produces errors. The goal is not to write perfect code on the first attempt. The goal is to read the error, understand it, and fix it efficiently.

🔍 Analogy: A Sat-Nav Recalculating

When you make a wrong turn, a sat-nav does not give up — it says "recalculating" and gives you a new route. A Python error message is the same thing: it is not telling you that you have failed, it is telling you exactly which turn was wrong so you can find your way back. The sat-nav that says nothing when you go wrong is far more dangerous than the one that speaks up.

There are three broad categories of error in Python. Understanding which category you are dealing with changes how you approach the fix:

CategoryWhen it happensWhat Python doesExample
Syntax ErrorBefore the program runs. Python cannot parse your code.Refuses to start. Points to the offending line.Missing colon after if, unmatched bracket.
Runtime ErrorWhile the program is running.Program crashes at the exact line where it occurred.Dividing by zero, accessing a missing key.
Logic ErrorWhile the program is running — or after.No crash. Program produces the wrong result silently.Using > instead of >=, adding when you meant to multiply.
💜 Logic errors are the hardest

Syntax and runtime errors are actually the easier bugs — Python tells you about them directly. Logic errors are silent: the program runs without complaint but produces the wrong answer. This article focuses on syntax and runtime errors, because those are the ones Python reports. Logic errors require a different skill — careful tracing — which you practise in the loop and conditional articles.

2   Anatomy of an Error Message

When Python encounters a runtime error, it prints a traceback. A traceback is a report showing the chain of function calls that led to the crash, followed by the error type and a description. Here is a real example:

Traceback (most recent call last):
  File "mission.py", line 12, in <module>
    result = calculate_fuel(speed, distance)
  File "mission.py", line 7, in calculate_fuel
    return distance / speed
ZeroDivisionError: division by zero

This looks intimidating at first. Let's dissect every part:

Part of the messageWhat it tells you
Traceback (most recent call last):A header. Tells you what follows is a traceback — a chain of calls leading to the crash. You can mostly ignore this line.
File "mission.py", line 12, in <module>The filename, the line number, and where in the code it was called from. <module> means it was called from the top level of the file (not inside a function).
result = calculate_fuel(speed, distance)The actual line of code that triggered the chain. Python shows you the source line so you can see it directly.
File "mission.py", line 7, in calculate_fuelThe crash happened inside a function called calculate_fuel, at line 7 of the file.
return distance / speedThe exact line where Python crashed.
ZeroDivisionError:The error type — the category of problem. This is the most important word to read.
division by zeroThe error message — a plain-English description of what went wrong.
💜 The three-step reading strategy

When you see a traceback, read it in this order:
1. Jump to the last line first — the error type and message tell you what went wrong.
2. Read the last file/line reference — this is where the crash happened.
3. Scroll up the traceback only if needed — the upper entries show you how you got there, which matters for bugs inside functions.

3   Where to Find Error Messages in VSCode

In VSCode, when you run a Python file, output and errors both appear in the Terminal panel at the bottom of the screen. If the terminal is not visible, open it with Ctrl + ` (backtick) on Windows/Linux, or Cmd + ` on macOS.

Error messages appear in red text. Normal program output appears in white. A typical session looks like this:

PS C:\Users\student\projects> python mission.py

Traceback (most recent call last):
  File "mission.py", line 12, in <module>
    result = calculate_fuel(speed, distance)
  File "mission.py", line 7, in calculate_fuel
    return distance / speed
ZeroDivisionError: division by zero

3.1   Clicking the Line Number in VSCode

VSCode makes one part of the traceback interactive: the filename and line number (e.g. mission.py, line 7) appears as a clickable link in the terminal. Clicking it jumps your cursor directly to that line in the editor. This is one of VSCode's most useful features — use it every time.

3.2   The Red Underline in the Editor

For syntax errors, VSCode often catches the problem before you even run the file — a red squiggly underline appears under the offending code. Hovering over it shows a tooltip with the error description. This is the fastest possible feedback loop: fix the syntax before you run, not after.

🔍 VSCode's red squiggle is your first line of defence

Before running your program, scan the editor for red underlines. VSCode's Python extension (Pylance) catches most syntax errors and many common mistakes — undefined variable names, wrong indentation, mismatched brackets — as you type. A clean editor with no red underlines does not guarantee the program is correct, but it does mean there are no obvious syntax problems.

4   The Common Error Types

Python has a specific name for every category of runtime error. Learning these names means you can recognise the problem the moment you see the last line of any traceback. Here are the eight you will encounter most often in Grade 9.

4.1   SyntaxError — "I can't read this"

A SyntaxError means Python cannot parse your code at all. The program never starts. Python found something that does not follow the rules of the language — a missing colon, an unclosed bracket, a misplaced keyword.

# Common causes of SyntaxError:

if score > 50          # missing colon
    print("pass")

print("hello"          # unclosed parenthesis

def calculate(a, b)    # missing colon after def
    return a + b

What you see in the terminal:

  File "ship.py", line 1
    if score > 50
                 ^
SyntaxError: expected ':'

The caret symbol ^ points to the position where Python got confused. Note that Python's pointer sometimes sits one character after the actual mistake — look at the character just before the caret too.

💜 How to fix a SyntaxError

Go to the line number shown. Read the line out loud and ask: is the colon there? Are all brackets closed? Is anything misspelled? VSCode's red squiggle will usually be sitting right on the problem before you even run the file.

4.2   IndentationError — "This line is in the wrong place"

Python uses indentation to define structure. An IndentationError means a line's indentation does not match what Python expects — either too many spaces, too few, or a mix of tabs and spaces.

def greet(name):
print("Hello,", name)    # should be indented
  File "ship.py", line 2
    print("Hello,", name)
    ^
IndentationError: expected an indented block after function definition on line 1
⚠️ Never mix tabs and spaces

VSCode inserts 4 spaces when you press Tab, which is correct Python style. If you paste code from somewhere that used actual tab characters, you may get an IndentationError even though the code looks correctly indented. The fix: select all the code, then use Edit → Convert Indentation to Spaces in VSCode. Or simply retype the indentation yourself.

4.3   NameError — "I've never heard of that"

A NameError means Python encountered a name — a variable or function — that has not been defined yet at that point in the program.

print(ship_name)         # ship_name was never assigned
Traceback (most recent call last):
  File "ship.py", line 1, in <module>
    print(ship_name)
          ^^^^^^^^^
NameError: name 'ship_name' is not defined

Common causes:

  • Typo in the variable name: shiip_name vs ship_name.
  • Using a variable before assigning it.
  • Using a local variable outside the function it was created in (scope — see Article 6).
  • Calling a function before defining it.
  • Forgetting to import a module: math.sqrt(4) without import math.

4.4   TypeError — "You can't do that with those types"

A TypeError means you tried to perform an operation on a value of the wrong type — adding a string to an integer, calling something that is not a function, or passing the wrong number of arguments.

age = input("Enter your age: ")
next_year = age + 1              # age is a string — can't add int to str
Traceback (most recent call last):
  File "ship.py", line 2, in <module>
    next_year = age + 1
                ~~~^~~
TypeError: can only concatenate str (not "int") to str

Common causes:

  • Forgetting to convert input() with int() or float().
  • Using + to concatenate a string and a number without converting.
  • Calling a non-function: result = 42().
  • Passing the wrong number of arguments to a function.

The error message usually tells you exactly which types are involved — read it carefully:

# "can only concatenate str (not 'int') to str"
# Translation: the left side is a string, the right side is an int — fix the types first.

4.5   ValueError — "The type is right, but the value doesn't make sense"

A ValueError means the type of your data is correct, but the actual content is not valid for the operation you are trying to perform.

age = int("hello")          # the type is str — that's fine for int()
                             # but "hello" cannot be converted to an integer
Traceback (most recent call last):
  File "ship.py", line 1, in <module>
    age = int("hello")
          ^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'hello'

Common causes:

  • Calling int() or float() on a string that is not a number.
  • Calling .remove() on a list when the item is not present.
  • Calling .index() on a list or string when the item is not present.

4.6   IndexError — "That position doesn't exist"

An IndexError means you tried to access a list or string at an index that is out of range — past the end (or before the beginning with a negative index that is too large).

crew = ["Alice", "Bob", "Carol"]
print(crew[5])               # only indices 0, 1, 2 exist
Traceback (most recent call last):
  File "ship.py", line 2, in <module>
    print(crew[5])
          ~~~~^^^
IndexError: list index out of range

Common causes:

  • Using a hardcoded index that is too large for the actual list.
  • Off-by-one error — using range(len(list)) correctly but then accidentally accessing list[len(list)].
  • An empty list: trying to access my_list[0] when the list is [].
  • A loop that runs one iteration too many.

4.7   KeyError — "That key doesn't exist in this dictionary"

A KeyError is the dictionary equivalent of an IndexError. You tried to access a key that is not in the dictionary.

ship = {"name": "Persephone", "fuel": 87.5}
print(ship["shields"])       # "shields" key does not exist
Traceback (most recent call last):
  File "ship.py", line 2, in <module>
    print(ship["shields"])
          ~~~~^^^^^^^^^^^
KeyError: 'shields'

Common causes:

  • Typo in the key name: "sheild" instead of "shield".
  • Assuming a key exists when it was never added.
  • Case mismatch: "Name" vs "name".

The fix: use in to check before accessing, or use .get() (see Article 9).

4.8   ZeroDivisionError — "You can't divide by zero"

Python raises this when the right-hand side of a division or modulo operation is zero. This is mathematically undefined, so Python refuses to proceed.

speed = 0
time = 100 / speed           # division by zero
Traceback (most recent call last):
  File "ship.py", line 2, in <module>
    time = 100 / speed
           ~~~~^~~~~~~
ZeroDivisionError: division by zero

Common causes:

  • A variable that should hold a non-zero number but was initialised to 0 and never updated.
  • User input that is 0 when the program did not guard against it.
  • Calculating an average on an empty list: sum(items) / len(items) when items is [].
✅ Check Your Understanding
  1. Match each error to its most likely cause:

    ErrorLikely cause
    NameError: name 'scroe' is not definedA. Forgetting to convert input()
    TypeError: can only concatenate str (not "int") to strB. Accessing a position past the end of a list
    IndexError: list index out of rangeC. Typo in a variable name
    KeyError: 'altitude'D. Accessing a key that was never added
    SyntaxError: expected ':'E. Missing colon after if or def
  2. For each error below, identify the type and explain in one sentence what is wrong:

    # Program 1
    name = input("Name: ")
    greeting = "Hello, " + name + " you are " + age + " years old."
    
    # Program 2
    planets = ["Mercury", "Venus", "Earth"]
    print(planets[3])
    
    # Program 3
    def launch():
    print("Liftoff!")
  3. A student gets this error. Without seeing their code, what two things do you know for certain?

    ZeroDivisionError: division by zero

5   Reading a Traceback Step by Step

Let's practise the three-step reading strategy on a realistic traceback. Here is a program and its error output:

5.1   The Program

# fleet_report.py

def get_average_fuel(fleet):
    total = 0
    for ship in fleet:
        total += ship["feul"]       # typo: "feul" instead of "fuel"
    return total / len(fleet)

fleet = [
    {"name": "Persephone", "fuel": 87.5},
    {"name": "Icarus IV",  "fuel": 43.0},
]

average = get_average_fuel(fleet)
print("Average fuel:", average)

5.2   The Error Output

Traceback (most recent call last):
  File "fleet_report.py", line 14, in <module>
    average = get_average_fuel(fleet)
  File "fleet_report.py", line 5, in get_average_fuel
    total += ship["feul"]
             ~~~~^^^^^^^^
KeyError: 'feul'

5.3   Applying the Three Steps

StepWhat you readWhat it tells you
1. Last lineKeyError: 'feul'The program crashed because it tried to access a dictionary key called 'feul' — which does not exist.
2. Last file/lineFile "fleet_report.py", line 5, in get_average_fuelThe crash happened on line 5, inside the function get_average_fuel.
3. The source linetotal += ship["feul"]There is a typo: "feul" should be "fuel". The key does not exist in the dictionary because it was spelled wrong.

The fix: change ship["feul"] to ship["fuel"] on line 5.

🔍 Notice: the error was called from line 14

The traceback shows two entries: the crash happened on line 5 (inside the function), but the call that triggered it was on line 14 (in the main program). If fixing line 5 does not make sense on its own, look at line 14 to understand how the function was called and with what data. Reading the full chain matters most when the bug is in the data being passed in rather than in the function itself.

6   A Quick-Reference Catalogue of Error Messages

Here are the most common error messages you will see in Grade 9, with plain-English translations and the most likely fix for each.

Error messagePlain EnglishMost likely fix
SyntaxError: expected ':'You are missing a colon at the end of an if, elif, else, for, while, or def line.Add the : at the end of that line.
SyntaxError: invalid syntaxPython hit something it could not parse. Often a typo, missing bracket, or incorrect keyword.Check the flagged line and the line above it for missing punctuation.
IndentationError: expected an indented blockThe line after a def, if, for, etc. is not indented.Indent the body of the block by 4 spaces.
IndentationError: unexpected indentA line is indented when it should not be.Remove the extra indentation from that line.
NameError: name 'x' is not definedPython has never seen the name x.Check for a typo in the name; make sure the variable is assigned before use.
TypeError: can only concatenate str (not "int") to strYou tried to join a string and an integer with +.Wrap the integer in str(), or convert the string with int().
TypeError: 'int' object is not callableYou put parentheses after a variable that holds a number, treating it like a function.Check for a variable with the same name as a function, e.g. len = 5 then len(items).
TypeError: missing N required positional argument(s)You called a function but did not pass enough arguments.Check the function definition and make sure you pass all required arguments.
ValueError: invalid literal for int() with base 10: 'x'You tried to convert a string to an integer but the string is not a number.Check what the user actually typed; validate input before converting.
IndexError: list index out of rangeYou accessed a list at a position that does not exist.Check your index value against len(list) - 1; look for off-by-one errors.
KeyError: 'x'You tried to access a dictionary with a key that is not there.Check the key spelling; use in or .get() to access safely.
ZeroDivisionError: division by zeroThe denominator in a division was zero.Guard with if denominator != 0: before dividing.
AttributeError: 'NoneType' object has no attribute 'x'You called a method on None — a variable that holds nothing.A function returned None when you expected a real value. Check for a missing return statement.
🟠 Common Confusion: "The error says line 14, but line 14 looks fine!"

Python sometimes reports the error at the line after the real mistake — especially for syntax errors. If the flagged line looks correct, look at the line immediately above it. For example, an unclosed parenthesis on line 13 might only cause a SyntaxError to be reported on line 14 when Python encounters the next statement and realises something is wrong.

Similarly, with runtime errors inside functions, the traceback may point to a line that is syntactically fine — the real cause is often in the data that was passed to the function, which you find by reading higher up the traceback.

7   A Debugging Workflow

Having a consistent process for fixing bugs makes the whole experience less stressful. Here is a workflow that works for beginners and professionals alike:

StepWhat to doWhy
1. Read the last lineWhat type of error is it? What does the message say in plain English?Identifies the category of problem before you look at any code.
2. Find the lineNote the filename and line number. Click the link in VSCode's terminal to jump there.Takes you directly to the crash site.
3. Read the source lineRead the exact line Python shows you. Can you see the problem?Often the bug is obvious once you are looking at the right place.
4. Check one line aboveLook at the line immediately before the flagged one.Syntax errors and missing colons often only show up on the following line.
5. Describe the bug in one sentenceBefore touching the keyboard, say aloud or write down what you think is wrong.Forces you to understand the problem before you attempt to fix it. Prevents random editing.
6. Make one changeFix the specific thing you identified. Do not change multiple things at once.If you change three things and the error disappears, you will not know which one fixed it.
7. Run againRun the program. Did the error go away? Did a new one appear?A new error after fixing the first is progress — not a step backwards.
💜 "Describe it before you fix it"

The single most important habit in debugging is step 5: describe the bug out loud before you touch anything. Students who skip this step tend to randomly delete lines, change variable names, and rewrite working code — making things worse. Students who describe the bug first almost always fix it in one targeted edit. Your teacher will ask you to do this during desk checks. Practise it now.

8   Worked Examples — Read, Diagnose, Fix

Here are four complete worked examples. For each one: read the code, read the error, apply the three-step strategy, and find the fix before reading the explanation.

Example 1

# Code
crew_count = 12
message = "Crew aboard: " + crew_count
print(message)
# Error
TypeError: can only concatenate str (not "int") to str

Diagnosis: crew_count is an integer. The + operator cannot concatenate a string and an integer.
Fix: message = "Crew aboard: " + str(crew_count)

Example 2

# Code
planets = ["Mercury", "Venus", "Earth", "Mars"]
for i in range(1, 5):
    print(planets[i])
# Error
IndexError: list index out of range

Diagnosis: The list has 4 items at indices 0–3. The loop runs i = 1, 2, 3, 4. When i = 4, planets[4] does not exist.
Fix: Change range(1, 5) to range(1, 4) — or better, use range(len(planets)), or simply for planet in planets.

Example 3

# Code
def warp_speed(distance, time)
    return distance / time

print(warp_speed(100, 5))
# Error
  File "ship.py", line 2
    def warp_speed(distance, time)
                                  ^
SyntaxError: expected ':'

Diagnosis: The def line is missing its colon.
Fix: def warp_speed(distance, time):

Example 4

# Code
def calculate_average(scores):
    total = sum(scores)
    average = total / len(scores)
    return average

result = calculate_average([])
print("Average:", result)
# Error
ZeroDivisionError: division by zero

Diagnosis: An empty list was passed in. len([]) is 0, causing division by zero.
Fix: Guard against an empty list before dividing:

def calculate_average(scores):
    if len(scores) == 0:
        return 0
    return sum(scores) / len(scores)

9   Final Check: The Big Picture

💡 Big Idea

An error message is information, not judgment. Every traceback has three key parts: the error type (last line), the crash location (filename and line number), and the source line (the code Python shows you). Read last-line first, find the line second, check one line above third. Describe the bug in one sentence before touching the keyboard. Errors are not obstacles — they are the fastest feedback you will ever get on what your program is actually doing.

✅ Final Check Your Understanding
  1. What are the three steps in the traceback reading strategy? Write them from memory.
  2. Read this traceback and answer the questions below:

    Traceback (most recent call last):
      File "mission.py", line 18, in <module>
        report = build_report(ship_data)
      File "mission.py", line 9, in build_report
        fuel_pct = ship["fuel_level"] * 100
                   ~~~~^^^^^^^^^^^^^^^
    KeyError: 'fuel_level'
    • What type of error occurred?
    • In which file and on which line did the crash happen?
    • What is the name of the function the crash happened inside?
    • In one sentence, describe the bug.
    • What are two possible causes of this specific KeyError?
  3. Below are four buggy programs. For each one: name the error type you expect to see, explain why the error will occur, and write the one-line fix.

    # Program A
    scores = [90, 85, 78]
    print(scores[3])
    
    # Program B
    temperature = input("Enter temperature: ")
    if temperature > 100:
        print("Too hot!")
    
    # Program C
    ship = {"name": "Argo", "crew": 50}
    print(ship["fuel"])
    
    # Program D
    for i in range(5)
        print(i)
  4. A student gets a NameError: name 'total' is not defined on the last line of their program. They are certain they created a total variable. Give two possible explanations for why Python still cannot find it.
  5. Explain why "describe the bug in one sentence before fixing it" is useful advice, rather than just immediately trying to fix the code.

10   Quick-Reference: Error Types at a Glance

Error TypeOne-line meaningFirst thing to check
SyntaxErrorPython cannot parse the code — it won't even start.Missing colon, unclosed bracket, typo in a keyword.
IndentationErrorA line is indented wrongly — too much, too little, or mixed tabs/spaces.Check indentation of the flagged line and the block it belongs to.
NameErrorPython has never heard of this variable or function name.Typo in the name; variable not yet assigned; out-of-scope local.
TypeErrorThe operation does not work with the types you gave it.Mixing strings and numbers; wrong number of arguments; calling a non-function.
ValueErrorThe type is right, but the value itself is not valid for this operation.int("hello"); .remove() on absent item; .index() on absent item.
IndexErrorYou accessed a position in a list or string that does not exist.Check index vs len() - 1; look for off-by-one; check for empty list.
KeyErrorYou accessed a dictionary key that is not there.Typo in key name; key never added; case mismatch. Use .get() or in.
ZeroDivisionErrorYou divided by zero.Guard with if denominator != 0; check for empty list before averaging.
AttributeErrorYou called a method on None or the wrong type.A function returned None — check for a missing return statement.