{"record":{"id":"c0891e8813b50434","repo":"python/cpython","slug":"coroutine-ignored-generatorexit","errorCode":null,"errorMessage":"coroutine ignored GeneratorExit","messagePattern":"coroutine ignored GeneratorExit","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Lib/_collections_abc.py","lineNumber":183,"sourceCode":"        Return next yielded value or raise StopIteration.\n        \"\"\"\n        if val is None:\n            if tb is None:\n                raise typ\n            val = typ()\n        if tb is not None:\n            val = val.with_traceback(tb)\n        raise val\n\n    def close(self):\n        \"\"\"Raise GeneratorExit inside coroutine.\n        \"\"\"\n        try:\n            self.throw(GeneratorExit)\n        except (GeneratorExit, StopIteration):\n            pass\n        else:\n            raise RuntimeError(\"coroutine ignored GeneratorExit\")\n\n    @classmethod\n    def __subclasshook__(cls, C):\n        if cls is Coroutine:\n            return _check_methods(C, '__await__', 'send', 'throw', 'close')\n        return NotImplemented\n\n\nCoroutine.register(coroutine)\n\n\nclass AsyncIterable(metaclass=ABCMeta):\n\n    __slots__ = ()\n\n    @abstractmethod\n    def __aiter__(self):\n        return AsyncIterator()","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_collections_abc.py#L165-L201","documentation":"Raised by collections.abc.Coroutine.close() (Lib/_collections_abc.py) when throwing GeneratorExit into a coroutine does not end it with GeneratorExit or StopIteration. Per PEP 342/492, a coroutine must not catch GeneratorExit and continue suspending; if it yields or returns a value while being closed, the machinery reports this RuntimeError.","triggerScenarios":"A coroutine's __await__/generator body wraps the suspension point in try/except that swallows GeneratorExit and yields again, or a custom class registered as Coroutine implements throw/send so that throw(GeneratorExit) resumes normally. Calling .close() (directly or via garbage collection / asyncio task cancellation teardown) then triggers it.","commonSituations":"Custom coroutine-like classes implementing __await__ with cleanup that catches BaseException too broadly; asyncio wrappers where a shielded await intercepts GeneratorExit; debugging why GC emits 'coroutine ignored GeneratorExit' during interpreter shutdown.","solutions":["In the coroutine body, catch GeneratorExit only to run cleanup, then re-raise it (bare 'raise') or return without suspending again.","Never yield/await again after GeneratorExit is delivered; move post-cleanup suspension out of the finally path.","Narrow existing 'except BaseException' handlers inside the coroutine to specific exceptions where possible.","For custom Coroutine subclasses, ensure throw() propagates GeneratorExit/StopIteration rather than returning normally."],"exampleFix":"# before\nasync def __await__body():\n    try:\n        yield\n    except BaseException:\n        yield 'cleanup-done'  # suspends again -> RuntimeError on close()\n\n# after\nasync def __await__body():\n    try:\n        yield\n    except GeneratorExit:\n        await_cancelled_cleanup()  # no further yield\n        raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    coro.close()\nexcept RuntimeError as e:\n    if 'coroutine ignored GeneratorExit' in str(e):\n        log.warning('misbehaving coroutine swallowed GeneratorExit: %r', coro)\n    else:\n        raise","preventionTips":["Never yield/await after catching GeneratorExit; re-raise it after cleanup.","Avoid 'except BaseException'/'except:' inside coroutine bodies.","Add an explicit close() path instead of relying on GC finalization."],"tags":["asyncio","coroutine","generator-exit","collections-abc"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}