TypeError: 'NoneType' object is not iterable — how to fix
Traceback (most recent call last):
File "app.py", line 9, in <module>
for item in get_items():
TypeError: 'NoneType' object is not iterable
Quick fix: Find which value is None (print it right before the line). Make sure the function returns a list on every path (return [] instead of falling off the end), don't assign the result of in-place methods (items.sort() returns None; use sorted(items)), and guard optional values: for x in items or []:.
What it means
Something tried to iterate over None: a for loop, tuple unpacking (a, b = value), list(), sorted(), sum(), in, *args expansion or ", ".join(...). Since Python 3.10 unpacking gives a slightly different message: TypeError: cannot unpack non-iterable NoneType object. Same causes, same fixes.
Find the culprit first:
result = get_items()
print(type(result), result)
Cause 1: the function has no return on some path
A function that ends without return returns None:
def get_items(user):
if user.active:
return user.items
# inactive users fall off the end -> None
for item in get_items(user): # TypeError
...
Fix: return an empty collection on every path.
def get_items(user):
if user.active:
return user.items
return []
The same happens when you print() a value instead of returning it.
Cause 2: assigning the result of an in-place method
list.sort(), list.append(), list.extend(), list.reverse(), dict.update(), random.shuffle() modify the object and return None:
items = items.sort() # items is now None
for x in items: ... # TypeError
Fix:
items.sort() # in place, don't reassign
# or
items = sorted(items) # returns a new list
Cause 3: unpacking a function that returns None
def load():
try:
return read_a(), read_b()
except OSError as e:
log(e) # returns None here
a, b = load() # cannot unpack non-iterable NoneType object
Re-raise the exception, or return a default tuple such as return None, None, and handle it at the call site.
Cause 4: an API, regex or lookup returned None
Many functions return None on "not found":
m = re.match(r"(\d+)-(\d+)", text)
start, end = m.groups() if m else (None, None)
data = response.json().get("items") # None if the key is missing
for item in data or []:
...
dict.get(key) returns None unless you pass a default: d.get("items", []). Test your patterns with the regex tester if a re.match unexpectedly returns None.
Cause 5: optional arguments defaulting to None
def process(values=None):
for v in values: # TypeError when called as process()
...
Fix:
def process(values=None):
if values is None:
values = []
for v in values:
...
Don't use values=[] as the default — mutable defaults are shared between calls.
Cause 6: pandas / ORM methods with inplace=True
df = df.dropna(inplace=True) sets df to None. Either use inplace=True without assignment, or drop inplace and assign: df = df.dropna().
Last updated 2026-11-05.