StopIteration Exception in Python Explained

StopIteration happens when an iterator has no more values to return.

This does not always mean something is broken. In Python, StopIteration is a normal signal used to say, “there are no more items.”

Beginners usually see it when:

  • calling next() too many times
  • using a while True loop with an iterator
  • reusing an iterator that is already finished
  • raising StopIteration manually inside a generator

If you use a for loop, Python usually handles this for you automatically. The exception becomes visible when you call next() yourself and do not handle the end of the iterator.

Quick fix

If you are calling next() manually, catch StopIteration:

numbers = iter([1, 2])

try:
    while True:
        print(next(numbers))
except StopIteration:
    print("No more items")

Output:

1
2
No more items

Use try-except when you call next() yourself. In a for loop, Python handles StopIteration automatically.

What StopIteration means

StopIteration is raised when an iterator has no more values to give.

Important points:

  • It is part of normal Python iteration
  • It does not always mean there is a bug
  • It is how Python knows an iterator is finished

For example, a list can be turned into an iterator with iter(). Each call to next() gets one item. When there are no items left, Python raises StopIteration.

If iterators are new to you, see iterators and iterable objects explained.

When beginners usually see this error

You will usually run into StopIteration in these situations:

  • Calling next() too many times
  • Reading past the end of a custom iterator
  • Raising StopIteration directly inside a generator
  • Using iterator code without checking when it is finished

A very common example is this:

numbers = iter([10, 20])

print(next(numbers))
print(next(numbers))
print(next(numbers))  # No more values left

The third call fails because the iterator is already exhausted.

Example that causes StopIteration

Here is a short example that raises the exception:

numbers = iter([1, 2])

print(next(numbers))
print(next(numbers))
print(next(numbers))

Output:

1
2
Traceback (most recent call last):
  ...
StopIteration

What happens here:

  • iter([1, 2]) creates an iterator
  • the first next(numbers) returns 1
  • the second returns 2
  • the third has nothing left to return, so Python raises StopIteration

Why for loops usually do not crash

A for loop uses next() behind the scenes.

For example:

numbers = [1, 2]

for number in numbers:
    print(number)

Output:

1
2

This loop stops cleanly because Python catches StopIteration internally.

That is why normal for loops do not usually show this error. The loop keeps calling next() until the iterator is finished, then it stops.

This is one reason for loops are often safer than manual iterator code.

How to fix it when using next()

Wrap next() in try-except

If you want to keep calling next() yourself, catch the exception:

numbers = iter([1, 2])

while True:
    try:
        value = next(numbers)
        print(value)
    except StopIteration:
        print("Finished")
        break

Output:

1
2
Finished

Use a default value with next()

You can avoid the exception by giving next() a default value:

numbers = iter([1, 2])

print(next(numbers, None))
print(next(numbers, None))
print(next(numbers, None))

Output:

1
2
None

The third call returns None instead of raising StopIteration.

This is often the simplest fix when None is an acceptable “no more data” value.

Stop calling next() when the iterator is finished

In many cases, the best fix is to use a for loop instead of manual next() calls:

numbers = iter([1, 2])

for value in numbers:
    print(value)

Output:

1
2

If your goal is just to loop through values, this is the easiest approach.

For more general exception handling, see how to handle exceptions in Python.

Generators and StopIteration

A generator is a function that yields values one at a time.

Generators end in a normal way when:

  • they reach the end of the function
  • they use return

Beginners should not manually raise StopIteration inside a generator.

Bad example

def count():
    yield 1
    raise StopIteration

In modern Python, this is not the right way to end a generator.

Good example

def count():
    yield 1
    return

Or even more simply:

def count():
    yield 1

When the generator finishes, Python handles the end correctly.

If you want to learn more, see generators in Python explained.

Debugging checklist

If you see StopIteration, check these things:

  • Check where next() is called
  • Check how many values the iterator contains
  • Print values before the failing call
  • See if a for loop can replace manual next() calls
  • If using a generator, remove manual raise StopIteration

Useful debugging lines:

print(next(my_iter))
print(list(my_iter))
print(type(my_iter))
print(hasattr(my_iter, '__next__'))

What these can help you find:

  • print(type(my_iter)) shows what kind of object you are working with
  • print(hasattr(my_iter, '__next__')) checks if it behaves like an iterator
  • print(list(my_iter)) shows remaining values, but it also consumes the iterator
  • print(next(my_iter)) helps test one step at a time

Be careful with this line:

print(list(my_iter))

It uses up the remaining items. After that, the iterator may already be exhausted.

Common causes

These are the most common reasons this exception appears:

  • Calling next() after the iterator is exhausted
  • Using next() in a while True loop without handling the end
  • Manually raising StopIteration inside a generator
  • Reusing an iterator that has already been consumed

Reusing a consumed iterator

This is another common mistake:

numbers = iter([1, 2, 3])

for n in numbers:
    print(n)

print("Second loop:")

for n in numbers:
    print(n)

Output:

1
2
3
Second loop:

The second loop prints nothing because the iterator was already consumed in the first loop.

FAQ

Is StopIteration always an error?

No. It is a normal signal that an iterator is finished. It becomes a visible error only when your code does not handle it.

Why does a for loop not show StopIteration?

Because Python handles it internally to stop the loop.

How do I avoid StopIteration with next()?

Use try-except or pass a default value like next(my_iter, None).

Should I raise StopIteration in a generator?

No. In generators, use return or let the function end naturally.

See also