zylon-ai/private-gpt · error · ValueError
Tools are not supported when structured output is enabled.
Error message
Tools are not supported when structured output is enabled.
What it means
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.
Source
Thrown at private_gpt/server/chat/chat_models.py:362
if self.tools is not None:
global_tool_context = self.tool_context or []
if global_tool_context:
for tool in self.tools:
if tool.context is None:
tool.context = global_tool_context
has_structured_output = bool(self.output_config and self.output_config.format)
if self.response_format.type == ResponseFormatType.json_schema:
has_structured_output = True
# Check that we don't have tools when structured output is enabled
if has_structured_output:
if self.tools:
if self.response_format.type == ResponseFormatType.json_schema:
raise ValueError(
"Tools are not supported when response_format is set to json_schema"
)
raise ValueError(
"Tools are not supported when structured output is enabled."
)
if self.mcp_servers:
raise ValueError(
"MCP servers are not supported when structured output is enabled."
)
if system.citations.enabled:
raise ValueError(
"Citations are not supported when structured output is enabled."
)
# Check unique tools
if self.tools:
tool_names = [tool.name for tool in self.tools]
if len(tool_names) != len(set(tool_names)):
raise ValueError(
"Duplicate tool names found in the tools list."
f" Provided tools: {self.tools}"View on GitHub (pinned to 4a030776a3)
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.
Example fix
# before
body = {"messages": m, "tools": tools, "output_config": {"format": fmt}}
# after
body = {"messages": m, "output_config": {"format": fmt}} if fmt else {"messages": m, "tools": tools} Defensive patterns
Strategy: validation
Validate before calling
structured = bool((body.get('output_config') or {}).get('format'))
assert not (structured and body.get('tools')), 'structured output excludes tools' Type guard
def no_structured_tool_clash(body: dict) -> bool:
structured = bool((body.get('output_config') or {}).get('format')) or \
body.get('response_format', {}).get('type') == 'json_schema'
return not (structured and body.get('tools')) Try / catch
except ValidationError as e:
if 'structured output' in str(e):
body.pop('tools', None); retry()
else:
raise Prevention
- 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)
When it happens
Trigger: 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.
Common situations: Feature flags for 'structured answers' and 'tools' both enabled; merging request payloads from different code paths; configuration presets that include tools by default.
Related errors
- Tools are not supported when response_format is set to json_
- MCP servers are not supported when structured output is enab
- Schema must define a 'type' field
- Array schemas must define 'items'
- Array 'items' must be a dictionary representing JSON Schema
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/95005f3e14903542.
Report an issue: GitHub.