StopIteration
What causes this
You called next() on an iterator that has no more items. Python raises StopIteration to signal the end of iteration. Normally for loops handle this automatically, but when you use next() directly or write custom generators, you need to handle it yourself.
Common scenarios:
- Using
next()on an empty generator expression - Calling
next()more times than there are items - A generator function that doesnβt yield anything for certain inputs
- Using
next()inside a generator (in Python 3.7+, this causes aRuntimeErrorinstead)
Fix 1: Provide a default value to next()
# β Raises StopIteration if no match
result = next(x for x in items if x > 100)
# β
Provide a default β returns None if no match
result = next((x for x in items if x > 100), None)
if result is not None:
print(f"Found: {result}")
The second argument to next() is returned when the iterator is exhausted instead of raising an exception.
Fix 2: Use a for loop instead
for loops handle StopIteration automatically:
# β Manual iteration β error-prone
it = iter(my_list)
first = next(it)
second = next(it) # StopIteration if list has only 1 item!
# β
For loop handles it
for item in my_list:
process(item)
Fix 3: Convert to a list first
If you need to check whether an iterator has items:
# β Can't check length of an iterator
it = (x for x in data if x > 0)
if len(it): # TypeError!
# β
Convert to list
matches = [x for x in data if x > 0]
if matches:
first = matches[0]
Note: this consumes the entire iterator into memory. Fine for small datasets, not ideal for large ones.
Fix 4: Wrap in try/except
When you genuinely need next() and canβt use a default:
it = iter(some_data)
try:
first = next(it)
second = next(it)
except StopIteration:
print("Not enough items in the iterator")
Fix 5: Fix generators that raise StopIteration
In Python 3.7+, a StopIteration inside a generator becomes a RuntimeError. If youβre calling next() inside a generator, catch it:
# β StopIteration leaks out of the generator (RuntimeError in 3.7+)
def first_match(items):
yield next(x for x in items if x > 0)
# β
Handle it explicitly
def first_match(items):
result = next((x for x in items if x > 0), None)
if result is not None:
yield result
Related resources
How to prevent it
- Always pass a default value to
next():next(iterator, default_value) - Prefer
forloops over manualnext()calls - When writing generators, never let
StopIterationpropagate β catch it or use defaults - Use list comprehensions instead of generator expressions when you need to check length or access by index
Related: Pip Install Error Fix