Common Python errors, explained
The tracebacks Python beginners and professionals hit most often: what each exception means, the exact message modern CPython prints, and the usual fix.
InteractivePaste a traceback and jump to the right fix. Open Error Message Decoder →
Python's error messages have improved a lot. Python 3.10 added "Better error messages", including precise bracket matching and "Did you mean" suggestions. Python 3.11 added fine-grained error locations that underline the exact failing expression with ^^^^. Python 3.12 can tell you to import a standard-library module you forgot. Still, a few exceptions account for most of the tracebacks people search for. The definitions below come from the official Built-in Exceptions page, and the example messages were reproduced on CPython 3.14.
| Exception | Parent class | One-line meaning |
|---|---|---|
SyntaxError | Exception | The parser couldn't read the code |
IndentationError / TabError | SyntaxError | Indentation is wrong, or mixes tabs and spaces |
NameError | Exception | A name isn't defined |
UnboundLocalError | NameError | A local variable is used before it gets a value |
TypeError | Exception | An operation was applied to the wrong type |
AttributeError | Exception | An attribute lookup or assignment failed |
KeyError / IndexError | LookupError | A dict key is missing, or a sequence index is out of range |
ValueError | Exception | The type is right but the value is not |
ModuleNotFoundError | ImportError | An import couldn't find the module |
ZeroDivisionError | ArithmeticError | Division or modulo by zero |
RecursionError | RuntimeError | The maximum recursion depth was exceeded |
IndentationError and TabError#
In Python, indentation is syntax. The interpreter uses it to decide which lines belong to a block. Three messages cover most cases:
IndentationError: expected an indented block after 'if' statement on line 1
IndentationError: unexpected indent
TabError: inconsistent use of tabs and spaces in indentation
TabError is a subclass of IndentationError, which is itself a SyntaxError (docs). PEP 8 recommends 4 spaces per indentation level and states that Python disallows mixing tabs and spaces. The fix is almost always to set your editor to insert spaces and re-indent the file. Code pasted from the web or chat apps often contains invisible tabs or non-breaking spaces.
SyntaxError (and the new, helpful messages)#
Old Python versions mostly said invalid syntax and pointed somewhere vaguely nearby. Since 3.10, the parser explains itself:
SyntaxError: '(' was never closed
SyntaxError: expected ':'
SyntaxError: invalid syntax. Perhaps you forgot a comma?
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
The last one is the classic Python 2 habit: print "hi" is a statement in Python 2 but a syntax error in Python 3. If the message points to a line that looks fine, check the line above it for an unclosed bracket or quote.
NameError: name 'x' is not defined#
NameError: name 'prnt' is not defined. Did you mean: 'print'?
NameError: name 'sys' is not defined. Did you forget to import 'sys'?
A NameError is raised "when a local or global name is not found" (docs). The causes are almost always a typo (Python is case-sensitive, so True is a built-in and true is not), a missing import, or using a variable outside the function that defines it. Since 3.12, a NameError inside a method can suggest 'self.blech' when you forgot the self. prefix (What's New 3.12).
UnboundLocalError: cannot access local variable#
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
count = 0
def tick():
count += 1 # assignment makes 'count' local
tick()count = 0
def tick():
global count
count += 1If a function assigns to a name anywhere in its body, Python treats that name as local for the whole function, so the read in count += 1 happens before any local value exists. The Python FAQ covers this exact case. global (or nonlocal for nested functions) fixes it, but passing values in and returning them is usually cleaner.
TypeError: 'NoneType' object is not subscriptable (and friends)#
A TypeError means an operation was applied to "an object of inappropriate type" (docs). The common forms:
TypeError: 'NoneType' object is not subscriptable
TypeError: unsupported operand type(s) for +: 'int' and 'str'
TypeError: can only concatenate str (not "int") to str
TypeError: 'int' object is not callable
scores = [42, 7, 19]
top = scores.sort() # sort() works in place, returns None
print(top[0])scores = [42, 7, 19]
top = sorted(scores) # returns a new list
print(top[0])NoneType errors usually trace back to a function that returned None: an in-place method, a function missing its return, or a lookup like re.match() that found nothing.
For 'int' and 'str', convert explicitly with int(text) or use an f-string, f"age: {age}". 'int' object is not callable usually means you named a variable after a built-in (sum = 0, then later sum(values)).
AttributeError: object has no attribute#
AttributeError: 'list' object has no attribute 'push'
AttributeError: 'NoneType' object has no attribute 'strip'
Either the method belongs to another type (Python lists use append, not JavaScript's push) or, again, the value is None. A common trap is naming your own file after a library, such as random.py or requests.py. Your file then gets imported instead of the real module, and its attributes are "missing". Since 3.10 the interpreter suggests close matches, for example Did you mean: namedtuple? (What's New 3.10).
KeyError and IndexError#
KeyError: 'b'
IndexError: list index out of range
Both are LookupError subclasses (docs). For dictionaries, use d.get("b", default) when a key is optional, or "b" in d to check first. For lists, remember that the last valid index is len(items) - 1. Off-by-one loops like range(len(items) + 1) are the usual culprit, and iterating directly (for item in items) avoids them.
ValueError#
ValueError: invalid literal for int() with base 10: '12a'
ValueError: too many values to unpack (expected 2, got 3)
The argument had the right type but an unusable value (docs). User input and file parsing are the usual sources. Strip whitespace, validate, and wrap conversions in try/except ValueError when the input isn't under your control.
ModuleNotFoundError: No module named 'x'#
ModuleNotFoundError: No module named 'requests'
The package isn't installed for the interpreter that's running your code. Machines often have several Pythons (system, Homebrew, pyenv, conda, one per virtual environment), and a bare pip may belong to a different one. The official guide recommends running pip as a module:
python -m venv .venv && source .venv/bin/activate
python -m pip install requests
python your_script.py
Also check that the import name matches the package. Some packages install under a different name than you import (for example, pip install beautifulsoup4 but import bs4).
ZeroDivisionError and RecursionError#
ZeroDivisionError: division by zero
RecursionError: maximum recursion depth exceeded
Guard divisions where the denominator can be zero, such as averages of empty lists. RecursionError fires when the depth passes sys.getrecursionlimit(), which is 1000 by default on CPython. A missing base case is the usual cause. Raising the limit with sys.setrecursionlimit treats the symptom and can crash the interpreter. Converting the recursion to a loop is the durable fix.
Debugging checklist#
- Read the traceback bottom-up: exception type, then message, then the last frame in your own code.
- Print the
type()andrepr()of the value on the failing line. - Check which interpreter you're running with
python -c "import sys; print(sys.executable)". - Use
breakpoint()to drop into the debugger right before the failure.
Frequently asked questions
How do I read a Python traceback?
Start at the bottom. The last line gives the exception type and message, and the frame just above it shows the file and line where it was raised. Move up the stack until you reach the first frame in your own code; that is usually where the fix belongs.
What does "'NoneType' object is not subscriptable" mean?
You used square brackets on a value that is None. Usually a function returned None (often because it has no return statement, or because you assigned the result of an in-place method such as list.sort()) and you then indexed into it.
Why do I get ModuleNotFoundError after pip install?
Most often, pip installed the package into a different Python interpreter or virtual environment than the one running your script. Install with python -m pip install package using the same python you run the script with, and make sure the right virtual environment is active.
What is the difference between TabError and IndentationError?
TabError is a subclass of IndentationError. It is raised specifically when a block mixes tabs and spaces inconsistently. Plain IndentationError covers other problems, such as a missing indented block after if or an unexpected indent.
Why does Python sometimes say "Did you mean"?
Since Python 3.10 the interpreter suggests close matches for misspelled names and attributes, and Python 3.12 added suggestions such as "Did you forget to import 'sys'?". These hints are added by the default error display, so some tools and REPLs with custom tracebacks may not show them.
Sources
Every factual claim on this page links to one of these. Checked October 2026. See how we source.
- Python docs: Built-in Exceptions docs.python.org
- Python docs: What's New in Python 3.10 (Better error messages) docs.python.org
- Python docs: What's New in Python 3.12 (Improved error messages) docs.python.org
- PEP 657: Include Fine Grained Error Locations in Tracebacks peps.python.org
- PEP 8: Indentation peps.python.org
- Python FAQ: Why am I getting an UnboundLocalError? docs.python.org
- Python docs: sys.getrecursionlimit docs.python.org
- Python docs: Installing Python Modules docs.python.org