TypeError: 'NoneType' object is not subscriptable
1 · The lesson
readWhat this error means
You used square brackets —x[0], x["name"], x[1:3] — on a value that is None. None holds nothing, so there's nothing to index into. The line that fails is rarely the line that's wrong: the real bug is wherever that None came from, usually a function that returned nothing when you expected a list, a dict or a match.
When you see it
Traceback (most recent call last):
File "report.py", line 4, in <module>
top = scores[0]
~~~~~~^^^
TypeError: 'NoneType' object is not subscriptableWhy it happens
Four sources ofNone account for almost all of them:
1. A method that changes things in place. list.sort(), list.append(), list.reverse(), dict.update() and random.shuffle() all modify the object and return None. Assigning the result throws your data away.
2. Your own function has a path with no return. A function that falls off the end returns None — often only for the one input you didn't test.
3. A lookup found nothing. dict.get(key) returns None for a missing key; re.match() and re.search() return None when the pattern doesn't match.
4. The data said null. A JSON field that's null arrives in Python as None.
scores = [72, 95, 88] scores = scores.sort() # sorts in place, returns None print(scores[0]) # TypeError: 'NoneType' object is not subscriptable
How to fix it
Don't assign the result of an in-place method. Either call it on its own line, or use the version that returns a new object:
scores = [72, 95, 88] scores.sort() # modifies scores; nothing to assign ranked = sorted(scores) # or: a new sorted list, original untouched print(ranked[0]) # 72
Check the lookup before you index it. A regex that didn't match is normal, not exceptional — handle it:
import re line = "ERROR disk full" m = re.match(r"(\w+) (.*)", line) if m is None: raise ValueError(f"unrecognised log line: {line!r}") level, message = m[1], m[2]
Give .get() a default of the right type. If you're going to index the result, the fallback should be indexable too:
user = {"name": "Grace"}
first_tag = user.get("tags", [""])[0] # "" rather than a crashMake every path in your function return something. Read it top to bottom and ask "what does this return when the if is false?" — that branch is where the None comes from.
When you'd actually see this in real code
rows = rows.sort(key=...)in a report script, and every laterrows[i]fails.- A scraper where
soup.find("h1")found nothing, and the next line indexes the result. response.json()["data"]["items"]where the API returned"data": nullfor an empty result.os.environ.get("CONFIG")[0:5]on a machine where the variable was never set.
Related errors
- TypeError: 'NoneType' object is not iterable — the same
None, used in aforloop instead of with[]. - AttributeError: 'NoneType' object has no attribute 'X' — the same
None, with a.method()instead of[]. - TypeError: 'int' object is not subscriptable — indexing the wrong type; this time a number.
See Also
- All Python errors — the full index, by type and by when it happens.
- Functions and scoping — returns, and what a function gives back when it has none.
- Lists and sequences — which list methods return a value and which change the list in place.
Practice this
on practicepython.inShort exercises that run in your browser and tell you what your code actually did, not just whether a test passed.