You run your script. Python stops and prints this:
TypeError: 'NoneType' object is not subscriptable
Short message, simple cause. A value you thought was a list, a dictionary or a number is really None, and your code treated it like something else. Below are the seven situations that trigger the error, the exact message each one gives, and how to fix it. I ran every example on Python 3.11, 3.12 and 3.14. All three print the same errors.
What the Error Means
None is Python's way of saying "nothing here". Its type is NoneType. You can't index it (x[0]), loop over it, unpack it, add it to a number or call it. Try any of those and Python raises a TypeError. The text after the colon names the operation that failed:
| Message | What your code tried to do |
|---|---|
'NoneType' object is not subscriptable |
Use [...] on None, such as x[0] or x["key"]
|
'NoneType' object is not iterable |
Loop over None with for, or pass it to list(), sum() or in
|
cannot unpack non-iterable NoneType object |
Unpack None into several names: a, b = None
|
unsupported operand type(s) for +: 'int' and 'NoneType' |
Do arithmetic with None |
'NoneType' object is not callable |
Call None as a function: x() where x is None |
None itself isn't the bug. The bug is whatever put None in your variable. The traceback shows where the value was used. The real cause sits a line or two above that.
How to Find the Cause Fast
Look at the line the traceback points to. Find the variable before the [, or the one after for. Print it right before that line:
print(repr(value)) # shows None, or the real value
Got None? Read upwards until you find the line that assigned it. It will be one of these seven things.
The Seven Causes
1. The Function Has No return
def average(numbers):
total = sum(numbers)
result = total / len(numbers) # computed, but never returned
scores = [80, 92, 75]
print(average(scores)[0]) # TypeError: 'NoneType' object is not subscriptable
The function works out result and then throws it away. A Python function with no return gives back None. So average(scores) is None, and [0] blows up. (Even with a return, [0] would still be wrong, since the function gives back one number and not a list. Fixing one mistake often shows you the next. That's normal.) Return the value:
def average(numbers):
total = sum(numbers)
return total / len(numbers) # hand the value back
scores = [80, 92, 75]
print(round(average(scores), 1))
2. You Assigned the Result of sort(), append() or reverse()
names = ["maya", "li", "omar"]
names = names.sort() # sort() sorts in place and returns None
print(names[0]) # TypeError: 'NoneType' object is not subscriptable
Some list methods change the list in place and return None on purpose. That covers sort(), append(), extend(), reverse() and insert(). So names = names.sort() sorts the list, then overwrites it with None. Call the method on its own line instead. Or use sorted(), which hands you a new list:
names = ["maya", "li", "omar"]
names.sort() # in place: do not assign the result
print(names[0])
# or keep the original and get a new list:
ordered = sorted(["maya", "li", "omar"])
print(ordered[0])
3. dict.get() Did Not Find the Key
users = {"ana": {"city": "Toronto"}}
profile = users.get("ben") # no such key, so .get() returns None
print(profile["city"]) # TypeError: 'NoneType' object is not subscriptable
When a key is missing, dict.get(key) quietly returns None. It doesn't raise a KeyError. That's handy, but it's on you to deal with the None. Test for it, or pass get() a default:
users = {"ana": {"city": "Toronto"}}
profile = users.get("ben")
if profile is None:
print("no such user")
else:
print(profile["city"])
# or give .get() a default:
print(users.get("ben", {}).get("city", "unknown"))
4. re.search() or re.match() Found Nothing
import re
text = "order: pending"
match = re.search(r"#(\d+)", text) # the text has no order number, so match is None
print(match[1]) # TypeError: 'NoneType' object is not subscriptable
Regex functions give you a match object when they find something. When they don't, you get None. If your text might not contain the pattern, check the result first. One side note: match.group(1) on None raises AttributeError: 'NoneType' object has no attribute 'group' instead. The cause is the same and so is the fix:
import re
text = "order: pending"
match = re.search(r"#(\d+)", text)
if match:
print(match[1])
else:
print("no order number found")
5. A Function Returns a Tuple on Some Paths and Nothing on Others
def min_max(values):
if values:
return min(values), max(values)
# an empty list falls off the end and returns None
low, high = min_max([]) # TypeError: cannot unpack non-iterable NoneType object
print(low, high)
Pass an empty list and the if is skipped. The function runs off the end with no return. The caller expects two values and gets a single None. Python words it as cannot unpack non-iterable NoneType object. Make the function return the same shape on every path:
def min_max(values):
if not values:
return None, None # always return the same shape
return min(values), max(values)
low, high = min_max([])
print(low, high)
6. A Loop Result Was Never Returned
def find_even(numbers):
evens = []
for n in numbers:
if n % 2 == 0:
evens.append(n)
# forgot: return evens
for n in find_even([1, 2, 3, 4]): # TypeError: 'NoneType' object is not iterable
print(n)
It's cause 1 again. The message differs, 'NoneType' object is not iterable, because the caller loops over the result instead of indexing it. Cause 2 can trigger it too, as in for x in some_list.sort():. See "not iterable" with NoneType? Check what produced the thing after in:
def find_even(numbers):
evens = []
for n in numbers:
if n % 2 == 0:
evens.append(n)
return evens
for n in find_even([1, 2, 3, 4]):
print(n)
7. print() Instead of return, Then Math on the Result
def tax(price):
print(price * 0.13) # prints, but returns None
total = 100 + tax(100) # TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
print() puts a value on the screen. The function still returns None. Beginners hit this a lot. You write a function that prints its answer, you check it by eye, the number looks right. Then you use it in a calculation and it fails. The message is unsupported operand type(s) for +: 'int' and 'NoneType'. Remember it this way: print is for people, return is for code.
def tax(price):
return price * 0.13
total = 100 + tax(100)
print(total)
A Related One: ‘NoneType’ Object Is Not Callable
Same family. A name you call like a function is holding None. Say handler = register(callback), where register returns nothing, and then you write handler(). The fix doesn't change. Find the line that assigned None. Nine times out of ten it's a function with no return.
How to Stop It From Coming Back
Three habits get rid of most of these errors.
Return on every path. If one branch returns a value, make all of them return something. An explicit None or an empty list is fine. The implicit None at the end of a function causes most of these bugs.
Know which standard calls return None. These can all hand you None: list.sort(), list.append(), list.reverse(), random.shuffle(), dict.get() (when the key is missing), re.match() and re.search() (when nothing matches), and print().
Check with is None. Write if value is None: and not if not value: when None is the case you care about. Why? not value is also true for 0, an empty string and an empty list. Type hints like -> list[int] | None also help, because your editor can warn you before you run anything.
Quick Reference
| Where the None came from | Fix |
|---|---|
Function with no return
|
Return the value |
x = x.sort(), x = x.append(...)
|
Call the method alone, or use sorted()
|
d.get(key) with a missing key |
Check for None, or pass a default |
re.search() found nothing |
if match: before using it |
| A return in only some branches | Return the same shape on every path |
print() used instead of return
|
Return the value, print it outside |
The Rule, Stated Once
'NoneType' object is not subscriptable means a variable you used as a list or dictionary is None. The traceback shows the line that used it. The line that caused it comes earlier: a missing return, an in-place method whose result you assigned, or a lookup that found nothing. So print the value, read upwards, and fix the source. Don't patch the line that fails.
Want more Python errors with a clear cause? Try IndexError: List Index Out of Range, UnboundLocalError, ModuleNotFoundError After pip install and Tkinter TclError: Image Doesn’t Exist. If Python is new to you, start with Python for Beginners.
Download the code: the broken and fixed versions of all seven causes are on GitHub in Python-projects/Troubleshooting/typeerror-nonetype. Run any file with python bug.py from inside its folder.
Top comments (0)