The errors every beginner hits, and what they mean
You can now read a traceback. This lesson is the reference for what each error type usually means in practice — not the textbook definition, but the two or three things that actually cause it.
Most of these you have already met somewhere in this course. Having them in one place is the point.
SyntaxError
SyntaxError: expected ':'
Python could not parse your file. Nothing ran at all — this is caught before execution starts, which distinguishes it from everything else here.
Usual causes:
- A missing colon after
if,for,whileordef - An unclosed bracket, quote or brace
=where you meant==- Python 2 code (
print "hello")
The reported line is often one after the real problem. If the line looks perfect, check the line above — an unclosed bracket on line 9 is only noticed on line 10.
values = [1, 2, 3
print("hello")
Python reports line 2, and line 1 is wrong.
IndentationError
IndentationError: expected an indented block after 'if' statement on line 4
A block opened and nothing was indented under it, or indentation is inconsistent.
The nastiest version is invisible: mixed tabs and spaces. The code looks aligned and is not. This is why the VS Code lesson had you switch on whitespace rendering; turn it on now if you skipped it.
TabError: inconsistent use of tabs and spaces in indentation is the explicit
form of the same problem.
NameError
NameError: name 'totl' is not defined
You used a name Python has never been told about. Three causes, in order of likelihood:
- A typo. Read the name in the message carefully — it is quoted exactly.
- Order. You used it on a line that runs before the line defining it. Functions and variables must be defined before use.
- Scope. It exists, but inside a different function.
UnboundLocalError is a specialised relative, covered in the scope lesson: you
assigned to the name somewhere in the function, which made it local everywhere
in that function.
TypeError
TypeError: can only concatenate str (not "int") to str
An operation was given the wrong type. The classics:
"I am " + 25 # str + int
len(42) # len() of a number
None + 1 # something returned None
"5" * "3" # two strings
sorted([1, "two"]) # cannot compare types
TypeError: 'NoneType' object is not subscriptable and
'NoneType' object has no attribute 'x' deserve special mention. NoneType
in a TypeError almost always means a function returned None and you used the
result. Look for a .sort(), .append() or similar whose result you
assigned, or a function missing a return.
Also common:
TypeError: greet() missing 1 required positional argument: 'city'
TypeError: greet() takes 2 positional arguments but 3 were given
Wrong number of arguments. The message names the function and the parameter, which usually solves it outright.
ValueError
ValueError: invalid literal for int() with base 10: 'abc'
The type was right, the value was not. int() wants a string, and got one —
but that string does not contain a number.
The distinction from TypeError is worth holding on to:
int("abc") # ValueError — a string, but not a numeric one
int(None) # TypeError — not a string at all
Other frequent ones:
int("") # ValueError — empty string
int("12.5") # ValueError — int() will not take a decimal
[1, 2].remove(99) # ValueError — not in list
a, b = [1, 2, 3] # ValueError — too many values to unpack
That last one appears when data is not the shape you assumed — a CSV row with four fields instead of three, say.
KeyError
KeyError: 'email'
That key is not in that dictionary. Always. The message is the key.
Causes:
- A typo or different capitalisation —
"Email"is not"email" - The data genuinely did not include that field
- You assumed an API response shape that is not guaranteed
The fix is .get() with a default when absence is normal, or try/except KeyError when it is not. Both are in the next lesson.
IndexError
IndexError: list index out of range
That position does not exist. Nearly always one of:
- Off by one — valid indexes stop at
len(list) - 1 - The list is empty and you asked for
[0] - You modified the list while looping over it
string index out of range is the same thing on a string.
AttributeError
AttributeError: 'list' object has no attribute 'push'
You called a method the object does not have. Either you have the wrong method
name — push is JavaScript, append is Python — or you have the wrong type of
object than you thought.
'str' object has no attribute 'append' # this is a string, not a list
'NoneType' object has no attribute 'strip' # it is None; something returned None
When surprised, check what the thing actually is:
print(type(value), repr(value))
repr() shows quotes and escapes, so you can see whether value is 5 or
"5", and whether that string has a trailing newline.
ZeroDivisionError
ZeroDivisionError: division by zero
Almost always an average over an empty collection:
average = sum(numbers) / len(numbers) # boom when numbers is empty
Guard it:
average = sum(numbers) / len(numbers) if numbers else 0
ModuleNotFoundError
ModuleNotFoundError: No module named 'requests'
Python cannot find that module. Usually:
-
Not installed —
pip install requests -
Installed into a different Python than the one running. The single most common cause, and the reason virtual environments exist (module 8). Check which Python you are actually on:
python -c "import sys; print(sys.executable)" -
Your own file is named after the module. A file called
random.pyin your folder shadows the standard library'srandom, and the failure is baffling. Never name a file after something you import.
RecursionError
RecursionError: maximum recursion depth exceeded
A function called itself with no way to stop. Even if you have not written recursion deliberately, this appears when two functions call each other in a loop.
A quick diagnosis table
| Message contains | Look for |
|---|---|
NoneType |
A function that returned None |
not defined |
A typo, or use before definition |
not subscriptable |
Indexing something that is not a list, string or dict |
not callable |
Brackets on something that is not a function — often a shadowed built-in |
unhashable type |
A list used as a dict key or set item |
not enough values to unpack |
Data is a different shape than assumed |
object is not iterable |
Looping over a number or None |
Practice
Trigger each deliberately, then fix it. Say the cause out loud before fixing.
SyntaxErrorfrom a missing colon, then from an unclosed bracket. Note the reported line in the second case.IndentationError.NameErrorfrom a typo, then from using a variable one line too early.TypeErrorfrom"age: " + 25, then from calling a function with too few arguments.ValueErrorfromint("abc"), then from unpacking three values into two.KeyError, then rewrite the line with.get().IndexErroron an empty list.AttributeErrorby calling.push()on a list.ZeroDivisionErrorby averaging an empty list, then guard it.- Create a file called
random.pycontainingimport random, run it, and read the confusing failure. Then rename it and appreciate why the rule exists.
Next: handling these deliberately instead of letting them stop your program.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship