These are the 20 Python common errors you hit most, each explained with its exact error text, what causes it, and how to fix it. A scannable reference for every Python developer.
“The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.”
Brian Kernighan
Last Updated: July 2026 | Tested on: Python 3.14.6 | Difficulty: Beginner | Reading Time: 20 minutes
Here is the good news about Python error messages: they repeat. Every Python developer trips over the same handful of them. You get a NameError when you misspell a variable. A TypeError when you try to add a string to an integer. An IndexError when you reach past the end of a list. An IndentationError when your spaces and tabs get tangled. Each one has a clear cause and a simple fix, once someone shows you what it is really saying.
Think of an error message like the warning light on a car dashboard. The first time it lights up, your stomach drops. Once you learn that the little oil can means “check the oil”, the panic goes away and you just deal with it. Python errors are the same. The red traceback looks scary, but it is a label telling you exactly what is wrong and on which line. This page is your dashboard guide for the 20 lights you will see most often.
Below you will find the 20 most common Python error messages explained, each one with its exact error text, the code that triggers it, and the one-line fix. Treat it as a troubleshooting reference you can search the moment an error you do not recognise pops up. By the end you will read a Python traceback the way you read a text message, calmly, instead of bracing for the worst.
These Python common errors will cross your screen hundreds of times over your career. Instead of pasting the same message into a search engine again and again, bookmark this page and jump straight to the entry you need using the quick reference table below.
Table of Contents
Quick Reference Table
Tip: click the diagram to open it full screen, then use the zoom and pan controls for a closer look.
The diagram sorts Python’s most frequent errors into groups: syntax errors (caught before your code even runs), name errors (a variable that was never defined), type errors (the wrong kind of operation on the wrong kind of value), value errors (the right type but the wrong content), and attribute errors (asking an object for something it does not have). Knowing the group is half the fix. A syntax error means check your punctuation. A type error means check your data types. Use this as a quick map when an unfamiliar traceback shows up.
| # | Error | Common Cause | Quick Fix |
|---|---|---|---|
| 1 | SyntaxError | Missing colon, bracket, or quote | Check the line above the error |
| 2 | IndentationError | Mixed tabs/spaces or wrong indent level | Use 4 spaces consistently |
| 3 | NameError | Variable not defined or misspelled | Check spelling, ensure variable exists |
| 4 | UnboundLocalError | Reading a local var before assignment | Use global or pass as parameter |
| 5 | TypeError (unsupported operand) | Wrong types in operation (str + int) | Convert types: str(n) or int(s) |
| 6 | TypeError (argument count) | Wrong number of arguments | Check function signature |
| 7 | TypeError (not subscriptable) | Indexing a non-sequence (int, None) | Check the variable type, add a None check |
| 8 | TypeError (not iterable) | Iterating over non-iterable (int) | Wrap in range() or fix variable |
| 9 | ValueError | Right type, wrong value (int("abc")) | Validate input before converting |
| 10 | IndexError | List index out of range | Check len() or use try/except |
| 11 | KeyError | Dict key doesn’t exist | Use .get(key, default) |
| 12 | AttributeError | Object doesn’t have that attribute | Check type with type(obj) |
| 13 | FileNotFoundError | File path is wrong or file missing | Check path, use Path.exists() |
| 14 | ModuleNotFoundError | Module not installed or misspelled | pip install module, check name |
| 15 | ImportError | Name doesn’t exist in module | Check available names with dir() |
| 16 | ZeroDivisionError | Division by zero | Check divisor before dividing |
| 17 | RecursionError | Infinite recursion / missing base case | Add/fix base case, use iteration |
| 18 | StopIteration | Calling next() on exhausted iterator | Use for loop or next(it, default) |
| 19 | OverflowError | Number too large for float | Use int (arbitrary precision) or decimal |
| 20 | UnicodeDecodeError | Wrong encoding for file/bytes | Specify encoding="utf-8" |
Syntax Errors
1. SyntaxError: invalid syntax
📄 error_01.py: missing colon after if
# Triggers: SyntaxError: expected ':'
# if x > 5
# print("big")
# Fix: add the colon
x = 10
if x > 5:
print("big")
The exact message you get is SyntaxError: expected ':'. Common causes: a missing colon after if, for, while, def, or class. A missing closing bracket or parenthesis. Using = instead of == inside a condition. Pro tip: a syntax error often points at the line after the real mistake, because Python only notices the problem once it reaches the next line. If the flagged line looks fine, check the line above it. It is like a sentence missing its closing quote mark: you only realise something is wrong when you reach the end and it never closes.
2. IndentationError: unexpected indent
📄 error_02.py: mixed or wrong indentation
# Triggers: IndentationError
# def greet():
# print("hello")
# print("world") # Extra indent!
# Fix: consistent 4-space indentation
def greet():
print("hello")
print("world")
greet()
▶ Output
hello world
The message here is IndentationError: unexpected indent. Fix: pick one indent style and stick to it. The Python world uses 4 spaces, never tabs. Set your editor to insert 4 spaces every time you press Tab. In Visual Studio Code (VS Code), open Settings and set “Editor: Tab Size” to 4 and turn on “Editor: Insert Spaces”. Think of indentation in Python like the lines on a parking lot: stay neatly inside them and everything fits, drift half a space over and the whole row gets confused.
Name and Scope Errors
3. NameError: name ‘x’ is not defined
📄 error_03.py
# Triggers: NameError: name 'username' is not defined # print(username) # Never assigned! # Common cause: a typo user_name = "Aditi" # print(username) # NameError: it is user_name, not username # Fix: check spelling, define before use print(user_name)
▶ Output
Aditi
The full message reads NameError: name 'username' is not defined. Nine times out of ten it is a spelling slip. Say you are storing a user named Aditi: you saved her in user_name but typed username, and Python has no idea who that is. It is like dialling a friend but tapping one wrong digit: the call goes nowhere because that number does not exist in your contacts. Check the spelling first, and make sure the name was assigned somewhere above the line that uses it.
4. UnboundLocalError: cannot access local variable
📄 error_04.py
count = 0
def increment():
# Triggers: UnboundLocalError
# count += 1 # Python thinks count is local because of the assignment
# Fix 1: use global keyword
global count
count += 1
increment()
print(count) # 1
# Fix 2 (better): pass as parameter and return
def increment_pure(c):
return c + 1
count = increment_pure(count)
print(count) # 2
▶ Output
1 2
The message is UnboundLocalError: cannot access local variable 'count' where it is not associated with a value. Here is the catch: the moment Python sees count += 1 inside the function, it decides count is a local variable, so it ignores the outer one entirely. Then it tries to read that local before you ever gave it a value, and complains. The clean fix is the second one shown above: pass the value in as a parameter and return the new value, rather than reaching out and changing a variable from inside the function.
Type Errors
5. TypeError: unsupported operand type(s)
📄 error_05.py
# Triggers: TypeError: can only concatenate str (not "int") to str
# result = "Age: " + 25
# Fix: convert to string
result = "Age: " + str(25)
print(result)
# Or use f-string (recommended)
age = 25
print(f"Age: {age}")
▶ Output
Age: 25 Age: 25
The raw message is TypeError: can only concatenate str (not "int") to str. Python will not quietly glue a number onto a string for you. Text and numbers are different shapes, like trying to plug a USB cable into a headphone socket. You have to convert first: wrap the number in str(), or skip the plus sign entirely and use an f-string, which is the cleaner habit to build.
6. TypeError: takes X positional arguments but Y were given
📄 error_06.py
def greet(name):
return f"Hello, {name}!"
# Triggers: TypeError: greet() takes 1 positional argument but 2 were given
# greet("Anvi", "Anvay")
# Fix: match the function signature
print(greet("Anvi"))
▶ Output
Hello, Anvi!
Say two friends named Anvi and Anvay both want a greeting. Pass both names to a function that wants one and you get TypeError: greet() takes 1 positional argument but 2 were given. The fix is simply to count: the message tells you how many the function expects and how many you handed it. It is like a recipe that asks for one tomato while you chopped in two. Match the call to the function signature and the error disappears.
7. TypeError: ‘NoneType’ object is not subscriptable
📄 error_07.py
# Common cause: function returns None, you try to index the result numbers = [3, 1, 2] result = numbers.sort() # sort() returns None! It sorts in-place. # print(result[0]) # TypeError: 'NoneType' object is not subscriptable # Fix: sort() modifies in-place, use sorted() for a new list sorted_nums = sorted(numbers) print(sorted_nums[0]) # 1
▶ Output
1
The message TypeError: 'NoneType' object is not subscriptable almost always means a function handed you None and you tried to index it with [0]. The classic trap is methods that change a list in place and return nothing, like list.sort(). People expect a sorted list back, but they get None. It is like a tailor who alters the clothes hanging in your own wardrobe: the job gets done, but nothing is handed back over the counter. When you want a new sorted list handed back to you, use sorted() instead, which returns the result.
8. TypeError: ‘int’ object is not iterable
📄 error_08.py
# Triggers: TypeError: 'int' object is not iterable
# for i in 5:
# print(i)
# Fix: use range()
for i in range(5):
print(i, end=" ")
print()
▶ Output
0 1 2 3 4
Writing for i in 5: gives you TypeError: 'int' object is not iterable. A loop needs something it can step through one item at a time, like a list or a range. A single number is not a collection of things, so there is nothing to step through. When you mean “do this 5 times”, wrap the number in range(5), which hands the loop the values 0 through 4.
Value and Index Errors
9. ValueError: invalid literal for int()
📄 error_09.py
# Triggers: ValueError: invalid literal for int() with base 10: 'hello'
# number = int("hello")
# Also triggers: int("3.14") cannot convert a float string directly
# number = int("3.14")
# Fix: validate or use try/except
user_input = "42"
try:
number = int(user_input)
print(f"Number: {number}")
except ValueError:
print(f"'{user_input}' is not a valid integer")
# For float strings: convert to float first, then int
print(int(float("3.14"))) # 3
▶ Output
Number: 42 3
The message is ValueError: invalid literal for int() with base 10: 'hello'. Notice the difference from a TypeError: here the type is fine, a string is exactly what int() accepts, but the contents make no sense as a whole number. Even "3.14" fails, because that is a float written as text. The safe habit, especially with anything a user typed, is to wrap the conversion in try/except so a bad value gives a friendly message instead of a crash.
10. IndexError: list index out of range
📄 error_10.py
fruits = ["apple", "banana", "cherry"]
# Triggers: IndexError: list index out of range
# print(fruits[5]) # Only indices 0, 1, 2 exist
# Fix: check length or use try/except
if len(fruits) > 5:
print(fruits[5])
else:
print(f"Only {len(fruits)} items, index 5 does not exist")
# Safe access with negative indexing
print(f"Last item: {fruits[-1]}")
▶ Output
Only 3 items, index 5 does not exist Last item: cherry
The message is IndexError: list index out of range. Remember that a list of 3 items has positions 0, 1, and 2, not 1, 2, 3. Asking for position 5 is like asking for the fifth person in a queue of three: there is nobody there. Check len() before you reach in, or use a negative index like fruits[-1] to grab the last item safely.
Key and Attribute Errors
11. KeyError: ‘missing_key’
📄 error_11.py
user = {"name": "Aviraj", "age": 30}
# Triggers: KeyError: 'email'
# print(user["email"])
# Fix 1: use .get() with default
email = user.get("email", "not provided")
print(f"Email: {email}")
# Fix 2: check first
if "email" in user:
print(user["email"])
else:
print("No email on file")
▶ Output
Email: not provided No email on file
The dictionary above stores a user named Aviraj, with just a name and an age. Ask it for a key it does not have, like user["email"] here, and you get KeyError: 'email'. A dictionary is like a coat check: hand over a ticket number that was never issued and the attendant has nothing to give you. The cleanest fix is user.get("email", "not provided"), which returns your default instead of raising when the key is missing. Use "email" in user when you want to branch on whether it exists.
12. AttributeError: ‘str’ object has no attribute ‘append’
📄 error_12.py
# Triggers: AttributeError: 'str' object has no attribute 'append'
# text = "hello"
# text.append(" world") # Strings don't have append!
# Fix: strings use concatenation or join
text = "hello"
text = text + " world" # Or: text += " world"
print(text)
# Common cause: a variable got reassigned to the wrong type
data = [1, 2, 3]
data = "oops" # type quietly changed from list to str
# data.append(4) # AttributeError: data is now a string!
▶ Output
hello world
The message is AttributeError: 'str' object has no attribute 'append'. An attribute is just something an object knows how to do. Lists know append, strings do not. So when this error shows up, the real question is “what type is this variable, really?” Often you started with a list and then accidentally reassigned the same name to a string somewhere above. A quick print(type(data)) tells you instantly what you are actually holding.
File and Import Errors
13. FileNotFoundError: No such file or directory
📄 error_13.py
from pathlib import Path
filepath = Path("data/config.json")
# Fix: check existence before opening
if filepath.exists():
content = filepath.read_text()
else:
print(f"File not found: {filepath}")
print(f"Current directory: {Path.cwd()}")
▶ Output
File not found: data\config.json Current directory: C:\Users\Rahul
If you skip the check and just open the file, you get FileNotFoundError: [Errno 2] No such file or directory: 'data/config.json'. The output above is from a Windows machine, which is why the paths show backslashes; on macOS or Linux you would see forward slashes. The “Current directory” line will show wherever you actually ran the script, so it will look different on your machine. Nearly every time, the real cause is that Python is looking in a different folder than you think.
It is like telling a delivery driver “third house on the left” without naming the street: the directions are fine, the starting point is wrong. Printing Path.cwd() like this answers the question “where am I standing right now”, which is usually all you need to spot the mistake.
14. ModuleNotFoundError: No module named ‘xyz’
The message reads ModuleNotFoundError: No module named 'xyz'. Causes: the module is not installed (run pip install xyz), the name is misspelled (it is import numpy, lowercase, not import NumPy), or you installed it in one Python but are running another (installed in system Python, running inside a virtual environment, or the reverse). Fix: install it with pip install module_name, then confirm it is there with pip list. A habit that prevents the mismatch entirely is python -m pip install, which guarantees the package lands in the exact Python you are running.
15. ImportError: cannot import name ‘xyz’
The message reads ImportError: cannot import name 'xyz' from 'module'. The difference from the previous error matters: here the module loads fine, but the specific name you asked for is not inside it. Causes: the name does not exist in that module, a typo in the name, or a circular import (module A imports from B while B imports from A, so neither finishes loading). Fix: list what the module actually offers with dir(module), and untangle any two files that import from each other.
Other Common Errors
16. ZeroDivisionError: division by zero
📄 error_16.py
def safe_average(scores):
if not scores:
return 0 # Guard against empty list
return sum(scores) / len(scores)
print(safe_average([90, 85, 92])) # 89.0
print(safe_average([])) # 0 (not ZeroDivisionError)
▶ Output
89.0 0
Divide by zero directly and Python raises ZeroDivisionError: division by zero. The fix is almost always a guard clause, like the if not scores check above: ask “could this divisor be zero?” before you divide, and hand back a sensible value when it can. An average of an empty list is not an error to crash on, it is just zero.
17. RecursionError: maximum recursion depth exceeded
The message is RecursionError: maximum recursion depth exceeded. Cause: a recursive function that never reaches its stopping point, so it keeps calling itself until Python gives up. It is like two mirrors facing each other, reflecting forever. Fix: make sure there is a base case that ends the recursion, and that every call moves closer to it. See Recursion for the full pattern.
18. StopIteration
📄 error_18.py
numbers = iter([1, 2]) print(next(numbers)) # 1 print(next(numbers)) # 2 # next(numbers) # StopIteration! # Fix: provide a default value print(next(numbers, "exhausted")) # "exhausted"
▶ Output
1 2 exhausted
Calling next() on an iterator that has run out raises a bare StopIteration. An iterator is like a Pez dispenser: every next() pops one item, and once it is empty the next press gives you nothing. You rarely see this error in real code, because a for loop catches it for you automatically. When you do call next() by hand, pass a default like next(it, "exhausted") so an empty iterator returns that value instead of raising.
19. OverflowError: math range error
The message is OverflowError: math range error. Cause: a float grew too big to represent, for example math.exp(1000). Here is a nice Python surprise: plain integers never overflow, because Python grows them as large as your memory allows. Only floats have a ceiling. Fix: stick to int arithmetic where you can, or reach for the decimal module when you need very large or very precise numbers.
20. UnicodeDecodeError: ‘utf-8’ codec can’t decode byte
The message looks like UnicodeDecodeError: 'utf-8' codec can't decode byte .... Cause: you are reading a file as utf-8 when it was actually saved in a different encoding like latin-1 or cp1252. It is like trying to read a French menu using English pronunciation rules: the letters are there, but the decoding goes wrong. Fix: tell Python the real encoding with open(file, encoding="latin-1"), or pass errors="replace" to swap any bad bytes for a placeholder instead of crashing.
How to Read Python Error Messages
Recognising individual Python common errors is useful, but reading any traceback cold is the real skill. A traceback can look like a wall of text, but it is really a story told from the bottom up. Read it like the last page of a mystery novel: the ending names the culprit, and you work backwards to see how it got there. Here is the order that works every time.
- Read the last line first. It names the error type and the message, that is, what actually went wrong.
- Find the bottom frame. That is the exact file and line where the error happened.
- Look at the caret markers. Python underlines the exact expression with
^^^^(and squiggles like~~~~), so you do not have to guess which part of the line broke. - Read upward through the frames to follow the call chain, that is, which function called which.
- Search the exact message. If you are still stuck, copy that last line into a search engine. Someone has hit it before you.
Conclusion
Error messages are not punishments, they are precise little reports. Each one tells you what went wrong, what type of problem it was, and exactly which line caused it. The 20 Python common errors in this post cover the vast majority of failures you will ever meet as a working developer. Once they stop looking scary, they start looking helpful, which is exactly what they were built to be.
Knowing what an error means is half the battle. In the debugging tutorial, you will learn how to hunt down and fix the bugs behind them, using print debugging, breakpoint(), pdb, and assert statements. And if you want to build up the fundamentals these errors keep pointing at, browse every lesson at the Python + AI/ML tutorial series home.
Practice Exercises
- Exercise 1: On purpose, write four tiny scripts that each trigger one error from this post: a
NameError, aTypeError, anIndexError, and aKeyError. Run each one and read the last line of the traceback out loud. Getting comfortable causing errors is the fastest way to stop fearing them. - Exercise 2: Write a function
safe_get(data, key)that returns a dictionary value, or the text"missing"when the key is not there, without ever raising aKeyError. Test it with a key that exists and one that does not. - Exercise 3: Build a small “input checker” that asks for a number with
input(), converts it withint(), and uses try/except to print a friendly message instead of crashing with aValueErrorwhen someone types “hello”.
Frequently Asked Questions
What is the most common Python error?
Among Python common errors, the pattern is clear: SyntaxError hits beginners most (missing colons, brackets), then NameError and TypeError for intermediate developers. As you get more experienced, KeyError and AttributeError become the most frequent.
How do I fix NameError in Python?
NameError means the variable was never defined or was misspelled. Check spelling carefully. Ensure the variable is defined before the line that uses it. Check if the variable is inside a function (local scope) when you’re trying to access it outside.
What does TypeError: unsupported operand type mean?
You tried an operation with incompatible types, like 'hello' + 5 (string + integer). Fix by converting types: 'hello' + str(5) or use f-strings: f'hello{5}'.
What causes IndexError: list index out of range?
You accessed a list index that doesn’t exist. A list with 3 items has indices 0, 1, 2. Accessing index 3 or higher raises IndexError. Check len(list) before accessing, or use negative indices for the end.
How do I fix KeyError in Python?
Use dict.get(key, default) instead of dict[key]. The .get() method returns the default value (None if not specified) when the key doesn’t exist, instead of raising KeyError.
What is the difference between SyntaxError and other errors?
SyntaxError happens before your code runs, because Python cannot even parse the code. All other errors happen during execution (runtime). A SyntaxError means the code is structurally wrong (a missing colon, an unmatched bracket), not logically wrong.
Interview Questions on Python Common Errors
Interviewers love asking about Python common errors because they reveal real experience. Here are the same ideas framed as scenarios you can practice out loud.
Q: What is the difference between a TypeError and a ValueError?
A TypeError means the type itself is wrong for the operation, like "age: " + 25, where Python refuses to add an integer to a string. A ValueError means the type is acceptable but the content is not, like int("hello"), where int() happily accepts strings but cannot make a number out of that one. A quick rule: TypeError is the wrong kind of thing, ValueError is the right kind of thing with bad contents.
Q: Your script runs fine on your laptop, but on the server it crashes with ModuleNotFoundError: No module named ‘requests’. You are sure you installed it. What do you check first?
Check which Python environment the server is actually running, because packages are installed per environment, not per machine. The usual culprit is a virtual environment that was never activated, or a package installed into the system Python while the script runs inside a venv (or the reverse). Run python -m pip list on the server with the same interpreter that runs the script, and install with python -m pip install requests so the package lands in the right place.
Q: A teammate writes result = my_list.sort() and then result[0] crashes with TypeError: ‘NoneType’ object is not subscriptable. What happened?
list.sort() sorts the list in place and returns None, so result is None and indexing it fails. The fix is either to keep using my_list after calling my_list.sort(), or to use sorted(my_list), which returns a new sorted list. This pattern generalises: whenever you see a NoneType error, some function in the chain returned None when you expected a value.
Q: Why does Python sometimes report a SyntaxError on a line that looks perfectly correct?
Because the real mistake is usually on an earlier line, most often an unclosed bracket, parenthesis, or quote. Python keeps parsing until the code stops making sense, and that moment often arrives on the next line. So when the flagged line looks fine, read the line or two above it and count your opening and closing brackets.
Q: Your data pipeline crashes with UnicodeDecodeError: ‘utf-8’ codec can’t decode byte while reading a client’s CSV export. How do you handle it?
The file was saved in a different encoding than UTF-8, commonly cp1252 or latin-1 from older Windows tools. First find the real encoding (ask the client, or inspect the file with a tool like chardet) and pass it explicitly: open(path, encoding="cp1252"). If a few corrupt bytes are acceptable, errors="replace" lets the read continue by substituting a placeholder character instead of crashing.
Q: What does UnboundLocalError tell you, and how is it different from a plain NameError?
A NameError means the name does not exist anywhere Python can see. An UnboundLocalError means the name does exist in the function, but you read it before it was assigned. It happens because any assignment inside a function, like count += 1, makes that name local for the entire function, so the outer variable is ignored. The clean fix is to pass the value in as a parameter and return the new value; global works too but couples the function to outside state.
Further reading: for the full reference, see the official Python documentation.
Related Posts
Previous: Python Project: Build an Expense Tracker (Files, JSON, Dicts)
Next: Python: Virtual Environments & Dependency Management
Series Home: Python + AI/ML Tutorial Series

No comment