GeneratorExit
PythonINFONotableControl FlowHIGH confidence

Generator's close() method was called

What this means

Raised when a generator or coroutine is closed by calling its `close()` method. This is a signal for the generator to perform any cleanup, like closing files or releasing resources.

Why it happens
  1. 1Explicitly calling `.close()` on a generator object.
  2. 2The generator object being garbage collected, which implicitly calls `.close()`.
  3. 3An external control flow change, like breaking out of a loop that is driving the generator.
How to reproduce

This exception is raised inside a generator when its `close()` method is invoked from outside.

trigger — this will error
trigger — this will error
def my_generator():
    try:
        print("Generator started")
        yield 1
    except GeneratorExit:
        print("Generator closing!")

g = my_generator()
print(next(g))
g.close() # This triggers the GeneratorExit

expected output

Generator started
1
Generator closing!

Fix 1

Use a `try...finally` block for cleanup

WHEN A generator needs to guarantee that a resource is released, regardless of how it exits.

Use a `try...finally` block for cleanup
def file_reader_gen(path):
    f = open(path, 'r')
    try:
        for line in f:
            yield line
    finally:
        print("Closing file.")
        f.close()

Why this works

The `finally` block is guaranteed to execute whether the generator is exhausted normally, closed with `.close()`, or garbage collected. This makes it the ideal place for cleanup code.

Fix 2

Use a `with` statement inside the generator

WHEN The resource you are managing is a context manager (like a file).

Use a `with` statement inside the generator
def file_reader_gen_with(path):
    with open(path, 'r') as f:
        for line in f:
            yield line
    print("File automatically closed.")

Why this works

The `with` statement automatically handles entering and exiting the context, which includes closing the file. This happens correctly even when `GeneratorExit` is raised.

Code examples
Triggerpython
def gen():
    yield 1
g = gen()
next(g)
g.close()  # sends GeneratorExit into generator
Handle with try/finallypython
def resource_gen():
    r = acquire()
    try:
        while True:
            yield r.next()
    except GeneratorExit:
        r.close()
        raise
Avoid issues with contextlibpython
from contextlib import contextmanager

@contextmanager
def managed():
    r = acquire()
    try:
        yield r
    finally:
        r.close()
What not to do

Yielding another value after catching `GeneratorExit`

After a generator has been signaled to close, it must not yield any more values. Doing so will result in a `RuntimeError`.

Same error in other languages
Sources
Official documentation ↗

cpython/Objects/genobject.c

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All Python errors