{"record":{"id":"90be8d6aaa152cbd","repo":"run-llama/llama_index","slug":"structuredllm-expected-a-self-output-cls-name","errorCode":null,"errorMessage":"StructuredLLM expected a {self.output_cls.__name__} instance from structured_predict, but got {type(output).__name__}: {output!r}. The underlying LLM failed to produce valid structured output.","messagePattern":"StructuredLLM expected a (.+?) instance from structured_predict, but got (.+?): (.+?)\\. The underlying LLM failed to produce valid structured output\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/llms/structured_llm.py","lineNumber":65,"sourceCode":"\n    @property\n    def metadata(self) -> LLMMetadata:\n        return self.llm.metadata\n\n    @llm_chat_callback()\n    def chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:\n        \"\"\"Chat endpoint for LLM.\"\"\"\n        # NOTE: we are wrapping existing messages in a ChatPromptTemplate to\n        # make this work with our FunctionCallingProgram, even though\n        # the messages don't technically have any variables (they are already formatted)\n\n        chat_prompt = ChatPromptTemplate(message_templates=messages)\n\n        output = self.llm.structured_predict(\n            output_cls=self.output_cls, prompt=chat_prompt, llm_kwargs=kwargs\n        )\n        if not isinstance(output, BaseModel):\n            raise TypeError(\n                f\"StructuredLLM expected a {self.output_cls.__name__} instance \"\n                f\"from structured_predict, but got {type(output).__name__}: \"\n                f\"{output!r}. The underlying LLM failed to produce valid \"\n                f\"structured output.\"\n            )\n        return ChatResponse(\n            message=ChatMessage(\n                role=MessageRole.ASSISTANT, content=output.model_dump_json()\n            ),\n            raw=output,\n        )\n\n    @llm_chat_callback()\n    def stream_chat(\n        self, messages: Sequence[ChatMessage], **kwargs: Any\n    ) -> ChatResponseGen:\n        chat_prompt = ChatPromptTemplate(message_templates=messages)\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/llms/structured_llm.py#L47-L83","documentation":"StructuredLLM (from llm.as_structured_llm(...)) wraps the underlying LLM's structured_predict and asserts the result is a pydantic BaseModel. If the wrapped LLM's structured-prediction machinery returns anything else (a plain dict, a string, None), it means the model output could not be coerced into the target schema, and StructuredLLM raises TypeError rather than emitting a chat response with an unusable payload.","triggerScenarios":"Calling structured_llm.chat(messages) (or complete(), which delegates to chat) where the underlying LLM cannot produce valid structured output for output_cls — weak models, missing function-calling support, or an output_cls that is not a pydantic v2 BaseModel so isinstance() fails.","commonSituations":"Using a small/local model (llama.cpp, Ollama without native structured output) with as_structured_llm; defining output_cls as a dataclass or pydantic v1 model while llama-index-core expects pydantic v2 BaseModel; prompt/schema so complex the model returns prose instead of JSON.","solutions":["Make output_cls a pydantic v2 BaseModel (inherit from pydantic.BaseModel) so isinstance(output, BaseModel) can pass.","Use a model with native function calling / structured output (OpenAI, Anthropic) or enable the integration's JSON/grammar mode.","Simplify the schema (fewer/optional fields) and add field descriptions so the model can comply.","Catch the TypeError and retry the chat call — transient malformed outputs often succeed on retry."],"exampleFix":"# before\nfrom dataclasses import dataclass\n@dataclass\nclass Answer: ...  # not a pydantic model -> isinstance fails\nsllm.chat(msgs)\n# after\nfrom pydantic import BaseModel\nclass Answer(BaseModel):\n    text: str\nsllm.chat(msgs)","handlingStrategy":"type-guard","validationCode":"from pydantic import BaseModel\n\ndef is_valid_output_cls(output_cls) -> bool:\n    return isinstance(output_cls, type) and issubclass(output_cls, BaseModel)","typeGuard":"from pydantic import BaseModel\n\ndef is_pydantic_v2_model(cls) -> bool:\n    return isinstance(cls, type) and issubclass(cls, BaseModel) and hasattr(cls, \"model_validate\")","tryCatchPattern":"try:\n    resp = structured_llm.chat(messages)\nexcept TypeError as e:\n    if \"StructuredLLM expected\" in str(e):\n        resp = structured_llm.chat(messages)  # single retry; transient parse failures are common\n    else:\n        raise","preventionTips":["Always define output_cls as a pydantic v2 BaseModel.","Prefer function-calling-capable models for structured output.","Keep schemas small with optional fields and clear descriptions."],"tags":["llama-index","structured-output","pydantic","type-error"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}