sgl-project/sglang · error · ValueError
Cannot combine tool calls with constrained decoding (text.fo
Error message
Cannot combine tool calls with constrained decoding (text.format / regex / ebnf / structural_tag / json_schema). Remove one.
What it means
The Responses-API request converter refuses tool calls combined with any constrained-decoding output constraint (text.format, regex, ebnf, structural_tag, or json_schema params). Both mechanisms compile to XGrammar constraints that would conflict, so the request is rejected rather than silently dropping one.
Source
Thrown at python/sglang/srt/entrypoints/openai/protocol.py:1827
# Apply any additional default parameters
for key, value in default_params.items():
if key not in params or params[key] is None:
params[key] = value
json_schema = self._json_schema_from_text_format(self.text)
if json_schema is not None:
params["json_schema"] = json_schema
has_existing_constraints = (
params.get("regex")
or params.get("ebnf")
or params.get("structural_tag")
or params.get("json_schema")
)
if tool_call_constraint and has_existing_constraints:
# Refuse rather than silently drop the tool-call grammar.
raise ValueError(
"Cannot combine tool calls with constrained decoding "
"(text.format / regex / ebnf / structural_tag / json_schema). "
"Remove one."
)
if tool_call_constraint:
constraint_type, constraint_value = tool_call_constraint
if constraint_type in ("structural_tag", "json_schema"):
params[constraint_type] = convert_json_schema_to_str(
constraint_value.model_dump(by_alias=True)
if hasattr(constraint_value, "model_dump")
else constraint_value
)
else:
params[constraint_type] = constraint_value
return params
View on GitHub (pinned to 0132848349)
Solutions
- Drop text.format/regex/ebnf/structural_tag/json_schema from the request and constrain arguments via the tool's parameters schema
- Or remove tools/tool_choice if structured text output is what you need
Example fix
// before
{"tools": [...], "tool_choice": "auto", "text": {"format": {"type": "json_schema", ...}}}
// after
{"tools": [...], "tool_choice": "auto"} Defensive patterns
Strategy: validation
Validate before calling
fmt = (body.get("text") or {}).get("format")
if body.get("tools") and fmt:
body["text"].pop("format") # or drop tools Type guard
def has_output_constraint(text): return bool((text or {}).get('format')) Try / catch
try: responses.create(...) except ValueError as e: if 'constrained decoding' in str(e): retry without text.format
Prevention
- Pick one mechanism: tool schemas OR output format, never both
- Lint request payloads in CI
When it happens
Trigger: POST /v1/responses with tools + tool_choice forcing calls, and text.format={...} or regex/ebnf/structural_tag/json_schema set in text.format params.
Common situations: Wanting schema-validated tool arguments and adding an output schema too; copying structured-output examples into a function-calling app; embedding json_schema in text.format while tools are attached.
Related errors
- tool_choice 'required' or a named tool cannot be combined wi
- Function tools must include a name.
- Assistant tool call function.arguments must be valid JSON.
- Assistant tool call function.arguments must be a JSON object
- No browser tool call found
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/05c89fcdbfc462e1.
Report an issue: GitHub.