{"record":{"id":"623d09438f0b7772","repo":"langchain-ai/langchain","slug":"asynctextprojection-requires-a-string-final-value","errorCode":null,"errorMessage":"AsyncTextProjection requires a string final value","messagePattern":"AsyncTextProjection requires a string final value","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/language_models/chat_model_stream.py","lineNumber":529,"sourceCode":"\n\nclass AsyncTextProjection(AsyncProjection):\n    \"\"\"String-specialized async projection for `.text` and `.reasoning`.\"\"\"\n\n    __slots__ = ()\n\n    def push(self, delta: str) -> None:\n        \"\"\"Append a text delta and notify waiters.\"\"\"\n        if not isinstance(cast(\"Any\", delta), str):\n            msg = \"AsyncTextProjection requires a string delta\"\n            raise TypeError(msg)\n        super().push(delta)\n\n    def complete(self, final_value: str) -> None:\n        \"\"\"Set the final accumulated text and notify waiters.\"\"\"\n        if not isinstance(cast(\"Any\", final_value), str):\n            msg = \"AsyncTextProjection requires a string final value\"\n            raise TypeError(msg)\n        super().complete(final_value)\n\n    def __aiter__(self) -> _AsyncTextProjectionIterator:\n        \"\"\"Return an async iterator over text deltas.\"\"\"\n        return _AsyncTextProjectionIterator(self)\n\n    def __await__(self) -> Generator[Any, None, str]:\n        \"\"\"Await the full accumulated text.\"\"\"\n        return self._await_text_impl().__await__()\n\n    async def _await_text_impl(self) -> str:\n        \"\"\"Return accumulated text or raise if the final value is not a string.\"\"\"\n        value = await self._await_impl()\n        if value is None:\n            return \"\"\n        if not isinstance(value, str):\n            msg = \"AsyncTextProjection received a non-string final value\"\n            raise TypeError(msg)","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/language_models/chat_model_stream.py#L511-L547","documentation":"`TypeError` from `AsyncTextProjection.complete`: the producer's final value is not a `str`. `complete` closes the async projection and wakes all awaiters (`await projection.text`); a non-string final value would flow into every consumer, so it is rejected at the source.","triggerScenarios":"Adapter code calling `projection.complete(value)` with a message object, `None`, or bytes instead of the final text — e.g. `complete(final_message)` or `complete(None)` for an empty stream — inside a custom async chat model integration.","commonSituations":"Completing `.text` with `AIMessage` instead of `AIMessage.content`/`.text`; empty-stream paths completing with `None`; exception handlers completing projections with sentinel objects.","solutions":["Always complete with a string; use `complete(\"\")` for empty streams.","Convert at the completion site: `projection.complete(msg.content if isinstance(msg.content, str) else \"\")`.","Ensure every termination path (success, error, cancellation) in the producer completes with a str or leaves the projection incomplete."],"exampleFix":"# before\nprojection.complete(final_message)  # not a str\n\n# after\nprojection.complete(final_message.text or \"\")","handlingStrategy":"type-guard","validationCode":"final = final_value if isinstance(final_value, str) else \"\"\nprojection.complete(final)","typeGuard":"def is_final_text(v: object) -> bool:\n    \"\"\"True when v is acceptable as an AsyncTextProjection final value.\"\"\"\n    return isinstance(v, str)","tryCatchPattern":"null","preventionTips":["Always complete with a str; \"\" for empty output","Ensure error/cancellation paths also complete with a string or not at all — never a sentinel object","Never call the untyped base AsyncProjection.complete on a text projection"],"tags":["streaming","async","typeerror","internal-api"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}