{"record":{"id":"e42baeddbdf6e981","repo":"langchain-ai/langchain","slug":"synctextprojection-requires-a-string-delta","errorCode":null,"errorMessage":"SyncTextProjection requires a string delta","messagePattern":"SyncTextProjection requires a string delta","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/language_models/chat_model_stream.py","lineNumber":296,"sourceCode":"        if self._error is not None:\n            raise self._error\n        return self._final_value\n\n\nclass SyncTextProjection(SyncProjection):\n    \"\"\"String-specialized sync projection.\n\n    Adds typed string producers and consumers, plus `__str__`, `__bool__`,\n    `__repr__` for ergonomic use with `.text` and `.reasoning` projections.\n    \"\"\"\n\n    __slots__ = ()\n\n    def push(self, delta: str) -> None:\n        \"\"\"Append a text delta.\"\"\"\n        if not isinstance(cast(\"Any\", delta), str):\n            msg = \"SyncTextProjection 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 mark the projection as done.\"\"\"\n        if not isinstance(cast(\"Any\", final_value), str):\n            msg = \"SyncTextProjection requires a string final value\"\n            raise TypeError(msg)\n        super().complete(final_value)\n\n    def __iter__(self) -> Iterator[str]:\n        \"\"\"Yield text deltas, raising if a producer supplied a non-string value.\"\"\"\n        for delta in super().__iter__():\n            if not isinstance(delta, str):\n                msg = \"SyncTextProjection received a non-string delta\"\n                raise TypeError(msg)\n            yield delta\n\n    def get(self) -> str:","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/language_models/chat_model_stream.py#L278-L314","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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`.","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`."],"exampleFix":"# before\nprojection.push(chunk)  # AIMessageChunk is not a str\n\n# after\nif chunk.text:\n    projection.push(chunk.text)","handlingStrategy":"type-guard","validationCode":"assert isinstance(delta, str), f\"text delta must be str, got {type(delta).__name__}\"\nprojection.push(delta)","typeGuard":"def is_text_delta(v: object) -> bool:\n    \"\"\"True when v can be pushed into a SyncTextProjection.\"\"\"\n    return isinstance(v, str)","tryCatchPattern":"null","preventionTips":["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"],"tags":["streaming","typeerror","internal-api"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}