langchain-ai/langchain · error · TypeError
AsyncTextProjection received a non-string final value
Error message
AsyncTextProjection received a non-string final value
What it means
Raised when awaiting an `AsyncTextProjection` (e.g. `stream.text()` on an async chat-model stream) and the stream's final aggregated value is neither `None` nor a `str`. The text projection is a typed view over the stream's completion value; this guard fires when the underlying model produced a final value of an unexpected type, such as a list of content blocks instead of plain text. It exists to surface contract violations early instead of silently returning garbage.
Source
Thrown at libs/core/langchain_core/language_models/chat_model_stream.py:547
raise TypeError(msg)
super().complete(final_value)
def __aiter__(self) -> _AsyncTextProjectionIterator:
"""Return an async iterator over text deltas."""
return _AsyncTextProjectionIterator(self)
def __await__(self) -> Generator[Any, None, str]:
"""Await the full accumulated text."""
return self._await_text_impl().__await__()
async def _await_text_impl(self) -> str:
"""Return accumulated text or raise if the final value is not a string."""
value = await self._await_impl()
if value is None:
return ""
if not isinstance(value, str):
msg = "AsyncTextProjection received a non-string final value"
raise TypeError(msg)
return value
# ---------------------------------------------------------------------------
# Sync stream
# ---------------------------------------------------------------------------
class _ChatModelStreamBase:
"""Shared state and event dispatch for chat-model streams.
Holds accumulated protocol state (text, reasoning, tool calls,
usage, metadata) and the event-dispatch machinery that drives the
typed projections. `ChatModelStream` (sync) and
`AsyncChatModelStream` (async) inherit from this base and add the
projection types and consumer APIs for their flavor.
"""
View on GitHub (pinned to e32fa9a52e)
Solutions
- If the model returns multimodal content (list blocks), consume the message objects (`stream.output` / iterating events) instead of the text projection.
- If you control the model subclass, make its final aggregated value a plain `str` (or `None`) so the text projection contract holds.
- Inspect the raw final value by awaiting the underlying stream directly to confirm which type is being produced before choosing a projection.
- If you never expect this state, wrap the await in `try/except TypeError` and fall back to reading the assembled `AIMessage`.
Example fix
// before const text = await stream.text(); // raises TypeError on list content # after (Python) text = await stream.text() if isinstance(msg := stream.output.content, str) else extract_text(msg.content)
Defensive patterns
Strategy: type-guard
Validate before calling
final = await stream._await_impl() if hasattr(stream, "_await_impl") else None
if final is not None and not isinstance(final, str):
raise TypeError("expecting text stream") Type guard
def is_text_projection_safe(value: object) -> bool:
return value is None or isinstance(value, str) Try / catch
try:
text = await stream.text()
except TypeError as e:
if "non-string final value" in str(e):
msg = stream.output # fall back to full message
text = msg.content if isinstance(msg.content, str) else str(msg.content)
else:
raise Prevention
- Prefer `stream.output.content` when the model may return multimodal content.
- Keep custom `_astream` implementations producing string-aggregatable final values.
- Unit-test the text projection against your model's actual content shape.
When it happens
Trigger: Awaiting `await stream.text()` (or the projection's `__await__`) on an async chat-model stream whose final aggregated value is a non-string, e.g. a provider returning multimodal `content` as a list of blocks, or a custom `_astream` implementation that completes with a non-string value.
Common situations: Using a custom chat model or a provider that emits multimodal / structured content while consuming the stream through the text-only projection; a subclass overriding `_await_impl` with a wrong return type; partial refactors of the streaming internals.
Related errors
- AsyncTextProjection received a non-string delta
- AsyncTextProjection requires a string delta
- AsyncTextProjection requires a string final value
- Stream finished without producing a message
- v2 stream finished without producing a message
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/d53a1e1b0bcf2044.
Report an issue: GitHub.