{"record":{"id":"1566a38113db7a5f","repo":"langchain-ai/langchain","slug":"synctextprojection-received-a-non-string-delta","errorCode":null,"errorMessage":"SyncTextProjection received a non-string delta","messagePattern":"SyncTextProjection received a non-string delta","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/language_models/chat_model_stream.py","lineNumber":311,"sourceCode":"        \"\"\"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:\n        \"\"\"Drain and return the full accumulated string, or empty if unfinished.\"\"\"\n        value = super().get()\n        if value is None:\n            return \"\"\n        if not isinstance(value, str):\n            msg = \"SyncTextProjection received a non-string final value\"\n            raise TypeError(msg)\n        return value\n\n    def __str__(self) -> str:\n        \"\"\"Drain and return the full accumulated string.\"\"\"\n        return self.get()\n\n    def __bool__(self) -> bool:\n        \"\"\"Return whether any deltas have been pushed.\"\"\"","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/language_models/chat_model_stream.py#L293-L329","documentation":"`TypeError` raised while iterating a `SyncTextProjection` (`for delta in projection`): a delta already sitting in the buffer is not a string. This is a second line of defense — even if a non-string slipped past `push` (possible via the untyped base class `SyncProjection.push`), iteration refuses to yield it to string-typed consumers.","triggerScenarios":"Calling `super().push(non_str)` on the base `SyncProjection` (bypassing the typed override), then iterating the projection; or sharing the underlying buffer between a generic and a text projection where one producer pushed a non-string.","commonSituations":"Subclassing `SyncTextProjection` and overriding `push` without the isinstance check; adapter code that mixes base-class pushes with text-projection iteration; corrupted producer state after an upstream exception handler pushes a sentinel object.","solutions":["Find the producer that inserted the non-string and fix it to push strings only (use the typed `SyncTextProjection.push`, which validates on entry — errorIndex 73's guard).","Do not bypass the typed API: never call `SyncProjection.push` directly on a text projection.","If mixed value types are legitimate, iterate the generic projection and stringify per item yourself."],"exampleFix":"# before: bypassing the typed push\nprojection.SyncProjection.push(chunk)  # non-str enters buffer\nfor delta in projection: ...  # TypeError here\n\n# after\nprojection.push(chunk.text or \"\")\nfor delta in projection: ...","handlingStrategy":"type-guard","validationCode":"# Validate buffer contents before iterating (detects bad producers early)\nfor d in list(projection._deltas):\n    assert isinstance(d, str), f\"non-string delta in buffer: {d!r}\"","typeGuard":"def text_projection_is_clean(proj) -> bool:\n    \"\"\"True when every buffered delta is a str (safe to iterate).\"\"\"\n    return all(isinstance(d, str) for d in proj._deltas)","tryCatchPattern":"null","preventionTips":["Route all writes through the typed push() so non-strings never enter the buffer","Never bypass the typed override via base-class push","Add unit tests that iterate after mixed producer paths"],"tags":["streaming","typeerror","internal-api"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}