{"record":{"id":"5d1abe7fe90e8915","repo":"langchain-ai/langchain","slug":"must-pass-in-a-non-empty-structured-output-schema","errorCode":null,"errorMessage":"Must pass in a non-empty structured output schema. Received: {schema_}","messagePattern":"Must pass in a non-empty structured output schema\\. Received: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/prompts/structured.py","lineNumber":71,"sourceCode":"    ) -> None:\n        \"\"\"Create a structured prompt template.\n\n        Args:\n            messages: Sequence of messages.\n            schema_: Schema for the structured prompt.\n            structured_output_kwargs: Additional kwargs for structured output.\n            template_format: Template format for the prompt.\n\n        Raises:\n            ValueError: If schema is not provided.\n        \"\"\"\n        schema_ = schema_ or kwargs.pop(\"schema\", None)\n        if not schema_:\n            err_msg = (\n                \"Must pass in a non-empty structured output schema. Received: \"\n                f\"{schema_}\"\n            )\n            raise ValueError(err_msg)\n        # Avoid mutating a caller-provided dict when merging extra kwargs.\n        structured_output_kwargs = dict(structured_output_kwargs or {})\n        for k in set(kwargs).difference(get_pydantic_field_names(self.__class__)):\n            structured_output_kwargs[k] = kwargs.pop(k)\n        super().__init__(\n            messages=messages,\n            schema_=schema_,\n            structured_output_kwargs=structured_output_kwargs,\n            template_format=template_format,\n            **kwargs,\n        )\n\n    @classmethod\n    def get_lc_namespace(cls) -> list[str]:\n        \"\"\"Get the namespace of the LangChain object.\n\n        For example, if the class is `langchain.llms.openai.OpenAI`, then the namespace\n        is `[\"langchain\", \"llms\", \"openai\"]`","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/prompts/structured.py#L53-L89","documentation":"Raised by the `StructuredPrompt` constructor when no output schema is supplied: the `schema_` positional/keyword argument is falsy and no `schema` key exists in `kwargs`. The schema defines the structure the piped model must produce via `with_structured_output`, so an empty/missing schema is a hard `ValueError`. The falsy check also rejects empty dicts/lists explicitly passed as schemas.","triggerScenarios":"`StructuredPrompt.from_messages_and_schema(messages)` with the schema argument omitted, `None`, or `{}`; or legacy call style `StructuredPrompt.from_messages_and_schema(messages, schema=None)`. Also triggers when a caller passes the schema under a misspelled keyword so `schema_` stays None.","commonSituations":"Copy-pasting `ChatPromptTemplate.from_messages` code and swapping only the class name, forgetting the required schema argument; building schemas dynamically and accidentally passing an empty Pydantic model or `{}` when a list of fields is empty; refactor renames (`schema` vs `schema_`) across versions.","solutions":["Pass a real schema as the second argument: a Pydantic model class (e.g. `class Joke(BaseModel): setup: str; punchline: str`) or a JSON-schema dict","If generating schemas dynamically, guard that the result is non-empty before constructing the prompt","Check the spelling of the parameter if passing by keyword — use the schema positional argument to avoid `schema_`/`schema` confusion"],"exampleFix":"# before\nprompt = StructuredPrompt.from_messages_and_schema(\n    [(\"system\", \"You are a comedian\")],\n)  # ValueError: Must pass in a non-empty structured output schema\n\n# after\nfrom pydantic import BaseModel\n\nclass Joke(BaseModel):\n    setup: str\n    punchline: str\n\nprompt = StructuredPrompt.from_messages_and_schema(\n    [(\"system\", \"You are a comedian\"), (\"human\", \"tell a joke about {topic}\")],\n    Joke,\n)","handlingStrategy":"type-guard","validationCode":"def is_usable_schema(schema: object) -> bool:\n    return schema is not None and schema != {} and schema != []","typeGuard":"from pydantic import BaseModel\n\ndef is_valid_schema(schema: object) -> bool:\n    if isinstance(schema, type) and issubclass(schema, BaseModel):\n        return len(schema.model_fields) > 0\n    return isinstance(schema, dict) and len(schema) > 0","tryCatchPattern":"try:\n    prompt = StructuredPrompt.from_messages_and_schema(messages, schema)\nexcept ValueError as e:\n    if \"non-empty structured output schema\" in str(e):\n        raise ValueError(\"provide a Pydantic model or JSON-schema dict\") from e\n    raise","preventionTips":["Define one Pydantic model per structured task and keep it non-empty","Validate dynamically built schemas have at least one field before use","Pass the schema positionally to avoid schema/schema_ keyword confusion"],"tags":["prompts","structured-output","pydantic","valueerror","missing-argument"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}