Common Python Errors β Exact Messages, Causes & Fixes
Every Python error tells you three things: what went wrong (the error type), where (file and line number), and why (the message after the colon). This guide lists the errors beginners hit most often, each with the exact message, the common causes, a code example that triggers it, and the fix.
SyntaxError
Exact message: SyntaxError: invalid syntax β also SyntaxError: expected ':'
Fix in one line: Python could not parse your code β usually a missing :, a stray = where == belongs, or an unclosed bracket/string.
Common causes
- A missing colon at the end of an
if,for,while, ordefline. - Using
=(assignment) instead of==(comparison) in a condition. - An unclosed quote, bracket, or parenthesis that swallows the rest of the file.
Code that triggers it
if x == 5 # missing colon
print(x)
How to fix it
Add the missing colon, swap = for ==, and let your editor highlight matching brackets. Read the caret (^) in the traceback β it points at the exact token Python choked on. Practice: missing colon after a function definition.
IndentationError
Exact message: IndentationError: expected an indented block β also IndentationError: unexpected indent
Fix in one line: Indent every block with exactly four spaces, consistently.
Common causes
- A line after
if/for/defthat is not indented at all. - Mixing tabs and spaces so two lines look aligned but are not.
- Copy-pasting code whose leading whitespace no longer lines up.
Code that triggers it
if True:
print("indented?") # must be indented
How to fix it
Indent the block body by four spaces, and never mix tabs with spaces β configure your editor to insert spaces for tabs. Practice: missing indentation after if.
NameError
Exact message: NameError: name 'x' is not defined
Fix in one line: Define the variable (or function) before you use it, and check the spelling.
Common causes
- Using a variable before assigning it.
- Calling a function before its
defline runs. - A typo in the name, or forgetting quotes so
hellois read as a variable instead of the string"hello".
Code that triggers it
print(age) # age never assigned
How to fix it
Move the assignment or def above the line that uses it, and double-check the spelling. Practice: using a variable before it's defined.
TypeError
Exact message: TypeError: can only concatenate str (not "int") to str β many variants exist
Fix in one line: Convert the values to a common type before combining them.
Common causes
- Adding a string and a number with
+. - Calling a non-function value like
my_list()orlen()(). - Iterating over a non-iterable such as an
int.
Code that triggers it
"The answer is " + 42 # can't add str and int
How to fix it
Convert explicitly β "The answer is " + str(42) or f"The answer is {42}" β and check the type of every value in the expression. Practice: mixing text and numbers in print.
IndexError
Exact message: IndexError: list index out of range
Fix in one line: Only index positions that exist β 0 to len(list)-1, or use -1 for the last item.
Common causes
- Using
list[3]on a 3-item list (valid indexes are 0, 1, 2). - A loop with
range(len(list))that runs one step too far. - Assuming a string index exists after a failed search or an empty list.
Code that triggers it
nums = [1, 2, 3]
print(nums[3]) # valid indexes: 0,1,2
How to fix it
Check len(nums) before indexing, use nums[-1] for the last element, or iterate with for x in nums so you never touch an index. Practice: wrong index to get the last item.
KeyError
Exact message: KeyError: 'age'
Fix in one line: Use dict.get(key, default) instead of dict[key] when the key may be missing.
Common causes
- Accessing a key that was never inserted.
- A typo in the key name.
- Deleting a key with
deland then reading it again.
Code that triggers it
data = {"name": "Alice"}
print(data["age"]) # 'age' key doesn't exist
How to fix it
Prefer data.get("age") (returns None or a fallback), or test if "age" in data: first. Practice: accessing a missing dictionary key.
ValueError
Exact message: ValueError: invalid literal for int() with base 10: 'abc' β also ValueError: too many values to unpack
Fix in one line: Validate (or catch) the bad value before the conversion, and match the number of unpacked values.
Common causes
- Calling
int()on text that is not a number. - Unpacking a sequence into too few or too many variables.
- Passing an out-of-range value to a function like
math.sqrt(-1).
Code that triggers it
int("hello") # can't convert string to int
How to fix it
Wrap the conversion in try/except ValueError, or validate the input first. Practice: converting text that isn't a number.
AttributeError
Exact message: AttributeError: 'str' object has no attribute 'append'
Fix in one line: Check type(value) where the error occurs and use a method that type actually has.
Common causes
- Calling a list method on a string (or vice versa).
- A typo in the method name, like
trim()instead ofstrip(). - A function returned
Noneand you chained a call on it.
Code that triggers it
numbers = "1,2,3" # a string, not a list!
numbers.append(4) # 'str' object has no attribute 'append'
How to fix it
Print type(numbers) just above the crash β method-name surprises usually mean the value is not the type you assumed. Practice: wrong method to remove whitespace.
ZeroDivisionError
Exact message: ZeroDivisionError: division by zero
Fix in one line: Guard the zero/empty case before dividing.
Common causes
- Averaging an empty list:
sum([]) / len([]). - Dividing by a counter that starts at zero and is never incremented.
- Taking modulo by zero.
Code that triggers it
average = total / count # crashes when count is 0
How to fix it
Handle the empty case explicitly: average = total / count if count else 0. Practice: dividing without checking for zero.
UnboundLocalError
Exact message: UnboundLocalError: local variable 'count' referenced before assignment
Fix in one line: Pass the value in and return the new one β or declare it global.
Common causes
- Reading a variable in a function that is assigned later in the same function.
- Incrementing a global counter without
global. - Shadowing a global name with a local assignment on a later line.
Code that triggers it
count = 0
def bump():
count = count + 1 # count is local here, read before assignment
return count
How to fix it
Best practice: def bump(count): return count + 1. If you must mutate a global, add global count as the first line. Practice: modifying a variable before it's assigned locally.
RecursionError
Exact message: RecursionError: maximum recursion depth exceeded
Fix in one line: Give the recursive function a base case that actually triggers.
Common causes
- A missing or unreachable base case.
- The recursive argument never converges (e.g.
countdown(n-2)skipping past 0). - A wrong condition that makes the base case compare the wrong value.
Code that triggers it
def countdown(n):
print(n)
countdown(n - 1) # missing: if n <= 0: return
How to fix it
Write the base case first, then the recursive step, and verify the argument moves toward the base case every call.
RuntimeError
Exact message: RuntimeError: dictionary changed size during iteration
Fix in one line: Never add or remove dict keys while iterating over that same dict.
Common causes
- Deleting keys inside a
for key in d:loop. - Adding keys while looping over
d.items(). - Calling a helper that mutates the dict mid-loop.
Code that triggers it
for key in prices:
if prices[key] == 0:
del prices[key] # RuntimeError
How to fix it
Iterate over a copy β for key in list(prices): β or build a new dict with a comprehension. Practice: modifying a dict while looping over it.
ImportError / ModuleNotFoundError
Exact message: ModuleNotFoundError: No module named 'pandas'
Fix in one line: Check the spelling, install the package, and don't name your file after a stdlib module.
Common causes
- The package is not installed.
- A typo in the module name.
- A local file (like
random.py) shadowing a standard-library module.
Code that triggers it
import matplotib.pyplot # typo β ModuleNotFoundError
How to fix it
Fix the spelling, run pip install, and rename any file that collides with a stdlib name.
StopIteration
Exact message: StopIteration β raised when next() runs past the end of an iterator
Fix in one line: Catch it, or pass a default to next().
Common causes
- Calling
next()one time too many. - Reusing an exhausted generator after it has already been fully consumed.
- A
whileloop with no stop condition on an iterator.
Code that triggers it
nums = iter([10, 20])
print(next(nums)); print(next(nums)); print(next(nums)) # StopIteration
How to fix it
Use next(nums, default) to return a fallback at the end, or wrap the loop in try/except StopIteration.
π¬ How to Read a Traceback, Top to Bottom
A traceback looks scary but is a fixed-shape story with three parts:
Traceback (most recent call last):
File "app.py", line 12, in <module> β 1. the chain of calls, newest last
File "app.py", line 7, in compute_total
return total / count
ZeroDivisionError: float division by zero β 2. the real message
β 3. read from the BOTTOM up
Work backwards: read the final line first (the error type and message), then the last frame above it (the exact file and line that crashed), then walk upward until you reach your code. In beginner programs, the top-most non-library frame is almost always where the wrong value was born one or two lines earlier.
π³ The Family Tree Behind the Names
Every exception above inherits from a small hierarchy rooted at BaseException. LookupError families (IndexError, KeyError) mean "you asked for something not there"; ArithmeticError families (ZeroDivisionError) mean "the maths was illegal"; NameError and AttributeError mean "this name doesn't exist here"; and TypeError/ValueError distinguish "wrong kind of thing" from "right kind, wrong value". Reading an error name as a branch of this tree finishes half the diagnosis before you read the message.
π‘οΈ Preventing Tomorrow's Errors Today
Three habits remove most of the errors above before they happen: convert input at the boundary β int(value) once, inside try/except ValueError, where the string enters your program. Validate emptiness at the start of any function that divides, indexes, or averages. And name things out loud β the two errors beginners most regret (UnboundLocalError and the stdlib-shadowing ImportError) are both naming problems.
πͺ Building Error Fluency on Purpose
The shortcut to fluency is to trigger errors deliberately: in the Playground, spend five minutes causing each error above β index past the end, divide by zero, mix tabs and spaces. Once you have made an error on purpose, you read it as a known visitor with a known cause, not a wall of red. PyDebug's fix-the-bug problems are built from exactly this idea β every problem is one of these error patterns wearing camouflage.
π Keep Going
- FixβtheβBug problems β practice every error above on real broken snippets.
- Python debugging guide β a systematic step-by-step method.
- 15 Common Python Errors Guide β deeper root-cause walkthroughs.
- Output prediction tricks β 10 tricky interview questions explained.
- Python glossary β every term used on this page, defined.