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

  1. If the model returns multimodal content (list blocks), consume the message objects (`stream.output` / iterating events) instead of the text projection.
  2. If you control the model subclass, make its final aggregated value a plain `str` (or `None`) so the text projection contract holds.
  3. Inspect the raw final value by awaiting the underlying stream directly to confirm which type is being produced before choosing a projection.
  4. 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

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


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/d53a1e1b0bcf2044. Report an issue: GitHub.