{"record":{"id":"2abd0454fe21fca1","repo":"langchain-ai/langchain","slug":"unexpected-generation-type","errorCode":null,"errorMessage":"Unexpected generation type","messagePattern":"Unexpected generation type","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/language_models/chat_models.py","lineNumber":2315,"sourceCode":"            if item is done:\n                break\n            yield item  # type: ignore[misc]\n\n    async def _call_async(\n        self,\n        messages: list[BaseMessage],\n        stop: list[str] | None = None,\n        callbacks: Callbacks = None,\n        **kwargs: Any,\n    ) -> BaseMessage:\n        result = await self.agenerate(\n            [messages], stop=stop, callbacks=callbacks, **kwargs\n        )\n        generation = result.generations[0][0]\n        if isinstance(generation, ChatGeneration):\n            return generation.message\n        msg = \"Unexpected generation type\"\n        raise ValueError(msg)\n\n    @property\n    @abstractmethod\n    def _llm_type(self) -> str:\n        \"\"\"Return type of chat model.\"\"\"\n\n    @deprecated(\"1.4.2\", alternative=\"asdict\", removal=\"2.0.0\")\n    @override\n    def dict(self, **_kwargs: Any) -> builtins.dict[str, Any]:\n        \"\"\"DEPRECATED - use `asdict()` instead.\n\n        Return a dictionary representation of the chat model.\n        \"\"\"\n        return self.asdict()\n\n    def asdict(self) -> builtins.dict[str, Any]:\n        \"\"\"Return a dictionary representation of the chat model.\"\"\"\n        starter_dict = dict(self._identifying_params)","sourceCodeStart":2297,"sourceCodeEnd":2333,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/language_models/chat_models.py#L2297-L2333","documentation":"`ValueError` raised in the async message-returning helper (used by `apredict`/`ainvoke` internals): after `agenerate` succeeds, `result.generations[0][0]` is not a `ChatGeneration`. The helper expects chat generations whose `.message` it can return; any other `Generation` subclass (plain `Generation`, `ChatGenerationChunk` misuse in custom results) is rejected.","triggerScenarios":"A custom `BaseChatModel` subclass whose `agenerate`/`_agenerate` builds a `ChatResult` containing non-`ChatGeneration` entries (e.g. plain `Generation(text=...)` copied from an LLM implementation), then the caller uses `ainvoke`/`apredict`-style paths.","commonSituations":"Porting an `LLM` (completion-style) subclass to `BaseChatModel` and reusing `Generation`; building `ChatResult` manually in test fakes with the wrong generation class; mixing v1 and v2 result shapes.","solutions":["Wrap messages in `ChatGeneration(message=...)`, not `Generation(text=...)`, inside custom `_agenerate`/`_astream` accumulation.","If you only need text, use the `LLM`/`BaseLLM` hierarchy instead of `BaseChatModel`.","Inspect `type(result.generations[0][0])` in a debugger to confirm which generation class is being produced.","Use `ChatResult(generations=[ChatGeneration(message=AIMessage(...))])` as the canonical return shape."],"exampleFix":"# before\nreturn ChatResult(generations=[[Generation(text=\"hi\")]])\n\n# after\nfrom langchain_core.outputs import ChatGeneration\nfrom langchain_core.messages import AIMessage\nreturn ChatResult(generations=[[ChatGeneration(message=AIMessage(content=\"hi\"))]])","handlingStrategy":"type-guard","validationCode":"result = await model.agenerate([messages])\ngen = result.generations[0][0]\nif not isinstance(gen, ChatGeneration):\n    raise TypeError(f\"custom model returned {type(gen).__name__}\")","typeGuard":"from langchain_core.outputs import ChatGeneration\ndef is_chat_generation(g: object) -> bool:\n    return isinstance(g, ChatGeneration)","tryCatchPattern":"try:\n    msg = await model.ainvoke(messages)\nexcept ValueError as e:\n    if \"Unexpected generation type\" in str(e):\n        # fix the custom _agenerate to return ChatGeneration, then retry\n        raise RuntimeError(\"custom model must return ChatGeneration\") from e\n    raise","preventionTips":["Always build `ChatResult` with `ChatGeneration` entries in custom models.","Add a contract unit test for custom `_generate`/`_agenerate` return shapes.","Don't port `Generation(text=...)` patterns from LLM subclasses into chat models."],"tags":["generations","type-mismatch","custom-model","async"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}