sgl-project/sglang · error · ValueError
thinking.budget_tokens is not allowed when thinking.type is
Error message
thinking.budget_tokens is not allowed when thinking.type is 'disabled'
What it means
Raised by the Anthropic-compatible endpoint's validator when a request sets thinking.type='disabled' but also supplies a budget_tokens value. Per the Anthropic contract, budget_tokens is only meaningful when thinking is enabled, so providing it alongside 'disabled' is rejected as a 400 before inference.
Source
Thrown at python/sglang/srt/entrypoints/anthropic/protocol.py:297
display: Optional[Literal["summarized", "omitted"]] = None
@model_validator(mode="after")
def _validate_thinking_shape(self):
# Cross-field rules mirror the SDK's three discriminated variants.
if self.type == "enabled":
if self.budget_tokens is None:
raise ValueError(
"thinking.budget_tokens is required when "
"thinking.type is 'enabled'"
)
if self.budget_tokens < 1024:
raise ValueError(
"thinking.budget_tokens must be >= 1024 "
"(got {})".format(self.budget_tokens)
)
elif self.type == "disabled":
if self.budget_tokens is not None:
raise ValueError(
"thinking.budget_tokens is not allowed when "
"thinking.type is 'disabled'"
)
if self.display is not None:
raise ValueError(
"thinking.display is not allowed when "
"thinking.type is 'disabled'"
)
elif self.type == "adaptive":
if self.budget_tokens is not None:
raise ValueError(
"thinking.budget_tokens is not allowed when "
"thinking.type is 'adaptive'"
)
return self
class AnthropicTaskBudget(BaseModel):View on GitHub (pinned to 0132848349)
Solutions
- Remove budget_tokens when thinking.type is 'disabled'
- Or switch thinking.type to 'enabled' if you actually want thinking
- Set budget_tokens to null/None instead of a number when disabling
Example fix
// before
{"thinking": {"type": "disabled", "budget_tokens": 2048}}
// after
{"thinking": {"type": "disabled"}} Defensive patterns
Strategy: validation
Validate before calling
if thinking["type"] == "disabled":
thinking.pop("budget_tokens", None) Prevention
- Build thinking dict per type, never mutate a shared template
- Omit keys rather than sending null
When it happens
Trigger: POST /v1/messages with {"thinking": {"type": "disabled", "budget_tokens": 1024}}. Any non-null budget_tokens together with type='disabled' triggers it.
Common situations: Toggling a previously-enabled thinking config to 'disabled' while leaving the budget field in place; building requests from a shared config object; SDK wrappers that always serialize budget_tokens even when unset becomes a number.
Related errors
- thinking.budget_tokens must be >= 1024 (got {})
- thinking.display is not allowed when thinking.type is 'disab
- thinking.budget_tokens is not allowed when thinking.type is
- Model is required
- max_tokens must be positive
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/6dad1ba6215be887.
Report an issue: GitHub.