{"record":{"id":"4165a703d1c3fa34","repo":"langchain-ai/langchain","slug":"expected-generate-to-return-a-chatresult-but-got","errorCode":null,"errorMessage":"Expected generate to return a ChatResult, but got {type(chat_result)} instead.","messagePattern":"Expected generate to return a ChatResult, but got (.+?) instead\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/language_models/fake_chat_models.py","lineNumber":281,"sourceCode":"        generation = ChatGeneration(message=message_)\n        return ChatResult(generations=[generation])\n\n    def _stream(\n        self,\n        messages: list[BaseMessage],\n        stop: list[str] | None = None,\n        run_manager: CallbackManagerForLLMRun | None = None,\n        **kwargs: Any,\n    ) -> Iterator[ChatGenerationChunk]:\n        chat_result = self._generate(\n            messages, stop=stop, run_manager=run_manager, **kwargs\n        )\n        if not isinstance(chat_result, ChatResult):\n            msg = (  # type: ignore[unreachable]\n                f\"Expected generate to return a ChatResult, \"\n                f\"but got {type(chat_result)} instead.\"\n            )\n            raise ValueError(msg)  # noqa: TRY004\n\n        message = chat_result.generations[0].message\n\n        if not isinstance(message, AIMessage):\n            msg = (\n                f\"Expected invoke to return an AIMessage, \"\n                f\"but got {type(message)} instead.\"\n            )\n            raise ValueError(msg)  # noqa: TRY004\n\n        content = message.content\n\n        if content:\n            # Use a regular expression to split on whitespace with a capture group\n            # so that we can preserve the whitespace in the output.\n            if not isinstance(content, str):\n                msg = \"Expected content to be a string.\"\n                raise ValueError(msg)","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/language_models/fake_chat_models.py#L263-L299","documentation":"`ValueError` in `FakeChatModel`-family `_stream`: `_generate` returned something that is not a `ChatResult`. The fake bridging code calls the model's own `_generate` and slices `chat_result.generations[0].message`, so it hard-requires the documented `ChatResult` return type; a custom subclass returning e.g. a message or string breaks it.","triggerScenarios":"Subclassing a fake chat model (`FakeChatModel`, used for testing) and overriding `_generate` to return an `AIMessage`, a `str`, a `ChatResult`-like dict, or `None`, then calling `stream`/`invoke` with streaming.","commonSituations":"Test doubles that shortcut `_generate` to return a plain message; refactors of test fakes after upgrading langchain-core; copying examples that predate the `ChatResult` contract.","solutions":["Return `ChatResult(generations=[ChatGeneration(message=AIMessage(content=...))])` from `_generate`.","Or override `_stream` directly instead of `_generate` if you want chunk-level control.","Use `FakeListChatModel`/`FakeMessagesListChatModel` as-is rather than subclassing with incompatible shapes.","Add a unit test asserting the return type of your override."],"exampleFix":"# before\ndef _generate(self, messages, **kw):\n    return AIMessage(content=\"hi\")\n\n# after\nfrom langchain_core.outputs import ChatResult, ChatGeneration\ndef _generate(self, messages, **kw):\n    return ChatResult(generations=[ChatGeneration(message=AIMessage(content=\"hi\"))])","handlingStrategy":"type-guard","validationCode":"from langchain_core.outputs import ChatResult\nresult = fake._generate(messages)\nif not isinstance(result, ChatResult):\n    raise TypeError(f\"_generate must return ChatResult, got {type(result)}\")","typeGuard":"from langchain_core.outputs import ChatResult\ndef returns_chat_result(value: object) -> bool:\n    return isinstance(value, ChatResult)","tryCatchPattern":"try:\n    for chunk in fake.stream(messages):\n        process(chunk)\nexcept ValueError as e:\n    if \"Expected generate to return a ChatResult\" in str(e):\n        raise TypeError(\"fix fake model _generate return type\") from e\n    raise","preventionTips":["Return `ChatResult(generations=[ChatGeneration(...)])` from all `_generate` overrides.","Add type assertions in test fixtures for fakes.","Prefer stock fakes (`FakeListChatModel`) over hand-rolled ones."],"tags":["fake-model","testing","type-mismatch","custom-model"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}