guidebeginner15 min
Debugging: Finding and Fixing Errors
Learn to read error messages, find bugs, and develop a systematic debugging mindset.
Prerequisites
Last updated: Jan 28, 2026
Bugs are inevitable. The skill isn't avoiding them—it's finding and fixing them efficiently. Professional programmers spend significant time debugging, and getting good at it will make you faster at everything.
Types of Errors
Syntax Errors
Mistakes in the code structure. Python catches these immediately:
python
# Missing colon
if x > 5
print("big")
# Mismatched parentheses
print("hello"
# Misspelled keyword
fro i in range(5):
print(i)Runtime Errors
Errors that happen while the program runs:
python
# ZeroDivisionError
result = 10 / 0
# IndexError
numbers = [1, 2, 3]
print(numbers[10])
# KeyError
person = {"name": "Alice"}
print(person["age"])
# TypeError
"hello" + 5Logic Errors
The hardest to find—code runs without error but gives wrong results:
python
# Bug: using = instead of ==
if x = 5: # Should be x == 5
print("five")
# Bug: off-by-one error
for i in range(10): # Should be range(11) to include 10
print(i)Reading Error Messages
Python's error messages are actually helpful. Let's decode one:
text
Traceback (most recent call last):
File "example.py", line 5, in <module>
result = calculate(numbers)
File "example.py", line 2, in calculate
return total / len(items)
ZeroDivisionError: division by zero- Read from bottom to top
- The last line tells you the error type: ZeroDivisionError
- The lines above show the "stack trace"—where the error occurred
- Line 2 in the calculate function is where division by zero happened
- Line 5 is where calculate was called
Print Debugging
The simplest debugging technique: add print statements to see what's happening:
python
def calculate_average(numbers):
print(f"DEBUG: numbers = {numbers}") # What did we receive?
print(f"DEBUG: length = {len(numbers)}")
total = sum(numbers)
print(f"DEBUG: total = {total}")
average = total / len(numbers)
print(f"DEBUG: average = {average}")
return average
# Now run it to see what's happening at each stepThe Debugging Process
- Reproduce the bug: Can you make it happen consistently?
- Isolate the problem: What's the smallest code that shows the bug?
- Form a hypothesis: What do you think is wrong?
- Test your hypothesis: Add prints or check values
- Fix and verify: Make the change and confirm it works
- Consider edge cases: What other inputs might cause problems?
Common Bugs and Fixes
python
# Bug: Modifying list while iterating
numbers = [1, 2, 3, 4, 5]
for n in numbers:
if n % 2 == 0:
numbers.remove(n) # BAD: modifies list during iteration
# Fix: iterate over a copy
for n in numbers[:]: # [:] creates a copy
if n % 2 == 0:
numbers.remove(n)
# Bug: Comparing floats for equality
if 0.1 + 0.2 == 0.3: # False! Floating point imprecision
print("equal")
# Fix: use approximate comparison
if abs((0.1 + 0.2) - 0.3) < 0.0001:
print("approximately equal")
# Bug: Forgetting to return
def add(a, b):
result = a + b # Calculates but doesn't return!
x = add(2, 3) # x is None
# Fix: add return statement
def add(a, b):
return a + bUsing try/except
Handle errors gracefully instead of crashing:
python
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
print("Cannot divide by zero")
return None
result = safe_divide(10, 0) # Prints warning, returns None
# Catch multiple error types
try:
value = my_dict[key]
result = int(value)
except KeyError:
print(f"Key '{key}' not found")
except ValueError:
print(f"Cannot convert '{value}' to integer")Practice
- Find and fix the bug: Why does sum_list([]) crash?
- Debug a function that should reverse a string but doesn't
- Fix an off-by-one error in a loop
- Handle potential errors when reading user input
- Add appropriate error handling to a file-reading function