{"record":{"id":"95005f3e14903542","repo":"zylon-ai/private-gpt","slug":"tools-are-not-supported-when-structured-output-is","errorCode":null,"errorMessage":"Tools are not supported when structured output is enabled.","messagePattern":"Tools are not supported when structured output is enabled\\.","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"private_gpt/server/chat/chat_models.py","lineNumber":362,"sourceCode":"        if self.tools is not None:\n            global_tool_context = self.tool_context or []\n            if global_tool_context:\n                for tool in self.tools:\n                    if tool.context is None:\n                        tool.context = global_tool_context\n\n        has_structured_output = bool(self.output_config and self.output_config.format)\n        if self.response_format.type == ResponseFormatType.json_schema:\n            has_structured_output = True\n\n        # Check that we don't have tools when structured output is enabled\n        if has_structured_output:\n            if self.tools:\n                if self.response_format.type == ResponseFormatType.json_schema:\n                    raise ValueError(\n                        \"Tools are not supported when response_format is set to json_schema\"\n                    )\n                raise ValueError(\n                    \"Tools are not supported when structured output is enabled.\"\n                )\n            if self.mcp_servers:\n                raise ValueError(\n                    \"MCP servers are not supported when structured output is enabled.\"\n                )\n            if system.citations.enabled:\n                raise ValueError(\n                    \"Citations are not supported when structured output is enabled.\"\n                )\n\n        # Check unique tools\n        if self.tools:\n            tool_names = [tool.name for tool in self.tools]\n            if len(tool_names) != len(set(tool_names)):\n                raise ValueError(\n                    \"Duplicate tool names found in the tools list.\"\n                    f\" Provided tools: {self.tools}\"","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/chat/chat_models.py#L344-L380","documentation":"The generic branch of the same structured-output guard: structured output is considered enabled (output_config.format set, or json_schema response_format) and tools are present, so ChatBody raises. It exists because this backend cannot run tool-calling loops while simultaneously constraining the final message to a structured schema.","triggerScenarios":"Setting output_config (e.g. {'format': ...}) alongside a non-empty tools list; enabling citation-free structured mode while tools remain registered from a previous request template.","commonSituations":"Feature flags for 'structured answers' and 'tools' both enabled; merging request payloads from different code paths; configuration presets that include tools by default.","solutions":["Pick one mode per request: structured output OR tools.","Make the request builder assert not (output_config and tools) before sending.","If tool-driven structured data is needed, model the schema as a tool and use tool_choice instead of output_config."],"exampleFix":"# before\nbody = {\"messages\": m, \"tools\": tools, \"output_config\": {\"format\": fmt}}\n\n# after\nbody = {\"messages\": m, \"output_config\": {\"format\": fmt}} if fmt else {\"messages\": m, \"tools\": tools}","handlingStrategy":"validation","validationCode":"structured = bool((body.get('output_config') or {}).get('format'))\nassert not (structured and body.get('tools')), 'structured output excludes tools'","typeGuard":"def no_structured_tool_clash(body: dict) -> bool:\n    structured = bool((body.get('output_config') or {}).get('format')) or \\\n        body.get('response_format', {}).get('type') == 'json_schema'\n    return not (structured and body.get('tools'))","tryCatchPattern":"except ValidationError as e:\n    if 'structured output' in str(e):\n        body.pop('tools', None); retry()\n    else:\n        raise","preventionTips":["Gate structured-output and tool features on one toggle","Review payload merges from different code paths before sending","Encode the exclusivity rule in the client SDK's types (union of modes)"],"tags":["validation","structured-output","tools","mutually-exclusive"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}