zylon-ai/private-gpt · error · AsyncIteratorError
Iterator next() operation failed: {e!s}
Error message
Iterator next() operation failed: {e!s} What it means
Wrapped as AsyncIteratorError by to_async_iterator when calling next() on the underlying synchronous iterator raises any exception other than StopIteration. The next() call runs in a thread-pool executor via loop.run_in_executor; any error raised by the source iterator's __next__ (I/O error, parsing error, or a bug in the generator) propagates and is re-raised with this message, chaining the original cause.
Source
Thrown at private_gpt/utils/async_utils.py:68
# Process items in chunks for better performance
chunk = []
for _ in range(chunk_size):
try:
def safe_next(it: Iterator[T]) -> T:
try:
return next(it)
except StopIteration:
return None # type: ignore
item = await loop.run_in_executor(
internal_executor, safe_next, iterator
)
if item is None: # Handle StopIteration gracefully
break
chunk.append(item)
except Exception as e:
raise AsyncIteratorError(
f"Iterator next() operation failed: {e!s}"
) from e
if not chunk:
break
# Process the chunk
for item in chunk:
try:
if transform_fn:
# Run transform in executor if it's CPU-intensive
result = await loop.run_in_executor(
internal_executor, transform_fn, item
)
yield result
else:
yield item
except Exception as e:View on GitHub (pinned to 4a030776a3)
Solutions
- Inspect the chained original exception (raise ... from e) - fix the root cause in the source iterator, not the wrapper
- Make the source iterator defensive: catch expected errors inside it and skip/log bad items instead of raising
- Ensure generators never let StopIteration escape from inside (PEP 479) - catch it and return explicitly
- If iterating a shared/closable resource, verify it is still open before yielding each item
Example fix
# before
def docs():
for f in paths:
yield parse(f.read()) # raises if f missing -> AsyncIteratorError
# after
def docs():
for f in paths:
try:
yield parse(f.read())
except OSError as e:
logger.warning(f"skipping {f}: {e}")
continue Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
from private_gpt.utils.async_utils import AsyncIteratorError
try:
async for item in to_async_iterator(iter(docs)):
process(item)
except AsyncIteratorError as e:
root = e.__cause__ # the real next() failure
logger.error("source iterator failed: %s", root, exc_info=root) Prevention
- Make the source iterator defensive: catch expected errors internally and skip/log bad items
- Never let StopIteration escape from inside a generator (PEP 479) - return explicitly
- Log the failing element inside the iterator before raising so failures are reproducible
- For network-backed iterators, retry transient errors inside __next__ instead of propagating
When it happens
Trigger: Passing a generator that reads files or hits the network and raises mid-iteration; passing an already-exhausted/closed generator whose next() raises RuntimeError (generator raised StopIteration internally, PEP 479); an iterator over a DB cursor whose connection dropped; a map/filter chain whose underlying callable throws on a specific item.
Common situations: Streaming ingestion from a source that fails partway (S3 object deleted, socket reset); iterators built over LangChain document loaders that raise on malformed documents; reusing a generator after it was closed; transform pipelines where an earlier exception surfaces only when the item is pulled.
Related errors
- Item transformation failed: {e!s}
- No items returned from astream_structured_predict
- Stream with this message_id already exists
- Async iterator conversion failed: {e!s}
- INVALID_REQUEST_ERROR
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/05b551f60e42ea05.
Report an issue: GitHub.