langchain-ai/langchain · error · TypeError
SyncTextProjection requires a string delta
Error message
SyncTextProjection requires a string delta
What it means
`TypeError` from `SyncTextProjection.push` (the string-specialized streaming buffer behind `.text`/`.reasoning` projections in `chat_model_stream`): a producer pushed a delta that is not a `str` (e.g. an `AIMessageChunk`, bytes, or `None`). The projection API is typed for strings only and enforces this at runtime to fail fast on producer bugs.
Source
Thrown at libs/core/langchain_core/language_models/chat_model_stream.py:296
if self._error is not None:
raise self._error
return self._final_value
class SyncTextProjection(SyncProjection):
"""String-specialized sync projection.
Adds typed string producers and consumers, plus `__str__`, `__bool__`,
`__repr__` for ergonomic use with `.text` and `.reasoning` projections.
"""
__slots__ = ()
def push(self, delta: str) -> None:
"""Append a text delta."""
if not isinstance(cast("Any", delta), str):
msg = "SyncTextProjection requires a string delta"
raise TypeError(msg)
super().push(delta)
def complete(self, final_value: str) -> None:
"""Set the final accumulated text and mark the projection as done."""
if not isinstance(cast("Any", final_value), str):
msg = "SyncTextProjection requires a string final value"
raise TypeError(msg)
super().complete(final_value)
def __iter__(self) -> Iterator[str]:
"""Yield text deltas, raising if a producer supplied a non-string value."""
for delta in super().__iter__():
if not isinstance(delta, str):
msg = "SyncTextProjection received a non-string delta"
raise TypeError(msg)
yield delta
def get(self) -> str:View on GitHub (pinned to e32fa9a52e)
Solutions
- At the push site, push the extracted string: `projection.push(chunk.text)` or `projection.push(str_value)` — never the chunk object.
- Guard optional content: `if chunk.text: projection.push(chunk.text)`.
- If you genuinely need to push non-string values, use the generic `SyncProjection` rather than `SyncTextProjection`.
Example fix
# before
projection.push(chunk) # AIMessageChunk is not a str
# after
if chunk.text:
projection.push(chunk.text) Defensive patterns
Strategy: type-guard
Validate before calling
assert isinstance(delta, str), f"text delta must be str, got {type(delta).__name__}"
projection.push(delta) Type guard
def is_text_delta(v: object) -> bool:
"""True when v can be pushed into a SyncTextProjection."""
return isinstance(v, str) Try / catch
null
Prevention
- Push extracted strings (chunk.text), never chunk objects
- Guard optional fields: if chunk.text: push(chunk.text)
- Type-hint producer helpers as (str) -> None so mypy catches bad push sites
When it happens
Trigger: Internal/extension code calling `projection.push(delta)` with a non-string — e.g. pushing a chat-model chunk object or `None` instead of `chunk.text`. This is an API-contract violation by the producer (usually custom model adapter code or misuse of the streaming internals), not by end users.
Common situations: Writing a custom chat model integration and pushing raw AIMessageChunk objects into `.text`; forgetting a `None` check for optional fields (e.g. `chunk.tool_call_chunks`) before pushing; porting code from the generic `SyncProjection` (untyped) to `SyncTextProjection`.
Related errors
- SyncTextProjection requires a string final value
- SyncTextProjection received a non-string delta
- SyncTextProjection received a non-string final value
- AsyncTextProjection received a non-string delta
- AsyncTextProjection requires a string delta
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/e42baeddbdf6e981.
Report an issue: GitHub.