---
title: "Common Python errors, explained"
url: https://erroneo.us/developers/python-errors/
description: "IndentationError, NameError, 'NoneType' object is not subscriptable, KeyError, ModuleNotFoundError and more: what each Python error means and how to fix it."
type: guide
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---

# 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.

Python's error messages have improved a lot. Python 3.10 added ["Better error messages"](https://docs.python.org/3/whatsnew/3.10.html), including precise bracket matching and "Did you mean" suggestions. Python 3.11 added [fine-grained error locations](https://peps.python.org/pep-0657/) that underline the exact failing expression with `^^^^`. Python 3.12 can [tell you to import a standard-library module you forgot](https://docs.python.org/3/whatsnew/3.12.html). Still, a few exceptions account for most of the tracebacks people search for. The definitions below come from the [official Built-in Exceptions page](https://docs.python.org/3/library/exceptions.html), 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](https://docs.python.org/3/library/exceptions.html#IndentationError)). [PEP 8](https://peps.python.org/pep-0008/#indentation) 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](https://docs.python.org/3/whatsnew/3.10.html):

```
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](https://docs.python.org/3/library/exceptions.html#NameError)). 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](https://docs.python.org/3/whatsnew/3.12.html)).

## 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 += 1
```

Why: If 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](https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value) 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](https://docs.python.org/3/library/exceptions.html#TypeError)). 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])
```

Why: `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](https://docs.python.org/3/whatsnew/3.10.html)).

## KeyError and IndexError

```
KeyError: 'b'
IndexError: list index out of range
```

Both are `LookupError` subclasses ([docs](https://docs.python.org/3/library/exceptions.html#LookupError)). 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](https://docs.python.org/3/library/exceptions.html#ValueError)). 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](https://docs.python.org/3/installing/index.html) 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()`](https://docs.python.org/3/library/sys.html#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.

>

If you're coming from JavaScript, many of these map directly. `NameError` is Python's [`ReferenceError: x is not defined`](https://erroneo.us/developers/javascript-errors/), and `'NoneType' object has no attribute` plays the role of `Cannot read properties of undefined`.

## Debugging checklist

- Read the traceback **bottom-up**: exception type, then message, then the last frame in your own code.
- Print the `type()` and `repr()` 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

1. [Python docs: Built-in Exceptions](https://docs.python.org/3/library/exceptions.html)
2. [Python docs: What's New in Python 3.10 (Better error messages)](https://docs.python.org/3/whatsnew/3.10.html)
3. [Python docs: What's New in Python 3.12 (Improved error messages)](https://docs.python.org/3/whatsnew/3.12.html)
4. [PEP 657: Include Fine Grained Error Locations in Tracebacks](https://peps.python.org/pep-0657/)
5. [PEP 8: Indentation](https://peps.python.org/pep-0008/#indentation)
6. [Python FAQ: Why am I getting an UnboundLocalError?](https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value)
7. [Python docs: sys.getrecursionlimit](https://docs.python.org/3/library/sys.html#sys.getrecursionlimit)
8. [Python docs: Installing Python Modules](https://docs.python.org/3/installing/index.html)

---
Source page: https://erroneo.us/developers/python-errors/ · More: https://erroneo.us/llms.txt
