{"record":{"id":"41e709238e9fdc64","repo":"zylon-ai/private-gpt","slug":"json-schema-must-be-provided-when-response-format","errorCode":null,"errorMessage":"JSON schema must be provided when response format is json_schema","messagePattern":"JSON schema must be provided when response format is json_schema","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"private_gpt/server/chat/chat_request_mapper.py","lineNumber":111,"sourceCode":"        return output_tools\n\n    async def _configure_output_cls_from_json_schema(\n        self,\n        request: ChatBody,\n    ) -> type[BaseModel] | None:\n        \"\"\"Define the output schema based on the response format.\"\"\"\n        if (\n            request.output_config\n            and request.output_config.format\n            and request.output_config.format.json_schema\n        ):\n            return create_model_from_json_schema(\n                request.output_config.format.json_schema\n            )\n\n        if request.response_format.type == ResponseFormatType.json_schema:\n            if not request.response_format.json_schema:\n                raise ValueError(\n                    \"JSON schema must be provided when response format is json_schema\"\n                )\n            return create_model_from_json_schema(request.response_format.json_schema)\n\n        # Default to None for text responses\n        return None\n\n    async def _collect_sampling_params(\n        self,\n        request: ChatBody,\n    ) -> dict[str, Any]:\n        \"\"\"Collect sampling parameters from the request request.\"\"\"\n        sampling_params: dict[str, Any] = {}\n        if request.seed is not None:\n            sampling_params[\"seed\"] = request.seed\n        if request.min_p is not None:\n            sampling_params[\"min_p\"] = request.min_p\n        if request.top_p is not None:","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/chat/chat_request_mapper.py#L93-L129","documentation":"Raised in chat_request_mapper while deriving the structured-output model: request.response_format.type is ResponseFormatType.json_schema but request.response_format.json_schema is None/empty. When you declare a json_schema response format you must supply the actual JSON schema payload, otherwise there is nothing from which to build the output model via create_model_from_json_schema.","triggerScenarios":"POST /v1/chat/completions (or the chat endpoint) with body {\"response_format\": {\"type\": \"json_schema\"}} and no json_schema field, while also not setting output_config.format.json_schema (the alternative field that takes precedence).","commonSituations":"OpenAI-style clients sending only {\"type\": \"json_schema\"} without a schema; version drift where the schema moved into output_config; typos like \"jsonSchema\" casing so the field is silently dropped.","solutions":["Provide the schema inline: response_format = {\"type\": \"json_schema\", \"json_schema\": {\"schema\": {...}}} (match the API's expected shape)","Or use the newer output_config.format.json_schema field, which is checked first","Verify with the server's OpenAPI spec which field name/shape the installed version expects after upgrades"],"exampleFix":"# before\n{\"response_format\": {\"type\": \"json_schema\"}}\n\n# after\n{\"response_format\": {\"type\": \"json_schema\", \"json_schema\": {\"name\": \"answer\", \"schema\": {\"type\": \"object\", \"properties\": {\"answer\": {\"type\": \"string\"}}, \"required\": [\"answer\"]}}}}","handlingStrategy":"validation","validationCode":"rf = body.get(\"response_format\") or {}\nif rf.get(\"type\") == \"json_schema\" and not (rf.get(\"json_schema\") or (body.get(\"output_config\") or {}).get(\"format\", {}).get(\"json_schema\")):\n    raise ValueError(\"response_format.type=json_schema requires response_format.json_schema\")","typeGuard":"def is_valid_response_format(body: dict) -> bool:\n    rf = body.get(\"response_format\") or {}\n    if rf.get(\"type\") == \"json_schema\":\n        return bool(rf.get(\"json_schema\")) or bool((body.get(\"output_config\") or {}).get(\"format\", {}).get(\"json_schema\"))\n    return True","tryCatchPattern":"try:\n    await client.chat(body)\nexcept ValueError as e:\n    if \"JSON schema must be provided\" in str(e):\n        body[\"response_format\"][\"json_schema\"] = {\"name\": \"out\", \"schema\": MY_SCHEMA}\n        await client.chat(body)\n    else:\n        raise","preventionTips":["Build response_format from one code path that always pairs type with schema","Add a payload schema/unit test asserting json_schema presence when type is json_schema","Re-check the field shape after server upgrades (output_config vs response_format)"],"tags":["chat","structured-output","json-schema","request-mapping"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}