langchain-ai/langchain · error · TypeError
AsyncTextProjection received a non-string delta
Error message
AsyncTextProjection received a non-string delta
What it means
`TypeError` from the async iterator of `AsyncTextProjection` (`async for delta in projection.text`): an item delivered from the projection's queue is not a string. It is the async counterpart of errorIndex 75 — a runtime check that catches non-string deltas that bypassed the typed `push` (e.g. via the untyped base `AsyncProjection.push`).
Source
Thrown at libs/core/langchain_core/language_models/chat_model_stream.py:509
if proj.error is not None:
raise proj.error
raise StopAsyncIteration
else:
proj._event.clear() # noqa: SLF001
await proj._event.wait() # noqa: SLF001
class _AsyncTextProjectionIterator(_AsyncProjectionIterator):
"""Async iterator over an `AsyncTextProjection`'s text deltas."""
__slots__ = ()
async def __anext__(self) -> str:
"""Return the next text delta."""
item = await super().__anext__()
if not isinstance(item, str):
msg = "AsyncTextProjection received a non-string delta"
raise TypeError(msg)
return item
class AsyncTextProjection(AsyncProjection):
"""String-specialized async projection for `.text` and `.reasoning`."""
__slots__ = ()
def push(self, delta: str) -> None:
"""Append a text delta and notify waiters."""
if not isinstance(cast("Any", delta), str):
msg = "AsyncTextProjection requires a string delta"
raise TypeError(msg)
super().push(delta)
def complete(self, final_value: str) -> None:
"""Set the final accumulated text and notify waiters."""
if not isinstance(cast("Any", final_value), str):View on GitHub (pinned to e32fa9a52e)
Solutions
- Push only strings through the typed `AsyncTextProjection.push` (validates on entry — errorIndex 78's guard): `await-safe projection.push(chunk.text)`.
- Guard optional fields before pushing: `if chunk.text: projection.push(chunk.text)`.
- Remove direct base-class `push`/`complete` calls from your adapter.
Example fix
# before
projection.AsyncProjection.push(chunk) # bypasses type check
async for delta in projection: ... # TypeError
# after
if chunk.text:
projection.push(chunk.text)
async for delta in projection: ... Defensive patterns
Strategy: type-guard
Validate before calling
assert isinstance(item, str), f"async text delta must be str, got {type(item).__name__}"
# push-side validation prevents this entirely:
if isinstance(delta, str):
projection.push(delta) Type guard
def is_async_text_delta(v: object) -> bool:
"""True when v is a valid AsyncTextProjection delta."""
return isinstance(v, str) Try / catch
null
Prevention
- Push strings only via the typed async push
- Do not override push/complete on AsyncTextProjection without re-adding the isinstance checks
- Cover async iteration in adapter unit tests
When it happens
Trigger: Producer code calling `AsyncProjection.push(non_str)` (base class) or an overriding subclass omitting the type check, followed by `async for delta in projection:` consuming the corrupted buffer. Affects `.text` and `.reasoning` async projections in streaming chat model code.
Common situations: Custom async model adapters pushing AIMessageChunk objects or `None` into `.text`; subclasses of `AsyncTextProjection` that override `push` without validation; migration from dict-based accumulation where values were sometimes non-string.
Related errors
- AsyncTextProjection requires a string delta
- AsyncTextProjection requires a string final value
- SyncTextProjection requires a string delta
- SyncTextProjection requires a string final value
- SyncTextProjection received a non-string delta
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/eeae2451aa3ec526.
Report an issue: GitHub.