sgl-project/sglang · error · ValueError
Reasoning parser '{self.reasoning_parser}' is always-on and
Error message
Reasoning parser '{self.reasoning_parser}' is always-on and cannot be disabled via Anthropic thinking What it means
The request tried to disable thinking (Anthropic thinking enabled=False) for a reasoning parser that SGLang classifies as always-on (e.g. its config special_case == "always" or the default mode resolves to "always"). Such models always produce reasoning and cannot be turned off, so disabling raises instead of silently failing.
Source
Thrown at python/sglang/srt/entrypoints/openai/serving_chat.py:2399
# Effort-conditioned, not toggled: "none" (0.0) is the off switch.
if not enabled:
request.reasoning_effort = "none"
return
config = self.template_manager.reasoning_config
is_mistral = (config is not None and config.special_case == "mistral") or (
config is None and self._reasoning_default_mode() == "mistral"
)
if is_mistral:
request.reasoning_effort = "medium" if enabled else "none"
return
is_always_on = (config is not None and config.special_case == "always") or (
config is None and self._reasoning_default_mode() == "always"
)
if is_always_on:
if not enabled:
raise ValueError(
f"Reasoning parser '{self.reasoning_parser}' is always-on "
f"and cannot be disabled via Anthropic thinking"
)
return
toggle_param = self._get_reasoning_toggle_param()
# The read side (``_get_reasoning_from_request``) returns False
# whenever ``config.toggle_param is None`` OR
# ``config.default_enabled is None``. The write side must mirror
# both conditions: if ``default_enabled`` is unset we cannot
# actually honor an ``enabled=True`` request even when the toggle
# name itself is resolvable, so writing the kwarg would set up the
# template to emit reasoning tokens while the parser ignores them
# (literal ``<think>`` markers leak into the assistant text).
config = self.template_manager.reasoning_config
read_side_supported = toggle_param is not None and (
config is None or config.default_enabled is not None
)View on GitHub (pinned to 0132848349)
Solutions
- Omit the thinking field entirely for always-on reasoning models
- Switch to a model whose reasoning is toggleable if disabling is a hard requirement
- Check the parser config's special_case/default mode to know which models are always-on
Example fix
# before
request.thinking = {"type": "disabled"} # always-on parser
# after
request.thinking = None Defensive patterns
Strategy: validation
Validate before calling
if thinking is not None and thinking.get('type') == 'disabled' and model_is_always_on_reasoner:
thinking = None Type guard
def is_always_on(parser_name) -> bool: return parser_name in ALWAYS_ON_PARSERS # e.g. per docs
Try / catch
except ValueError as e: if 'always-on' in str(e): drop thinking param and resend
Prevention
- Don't send thinking disabled by default
- Check parser special_case before toggling
- Cache per-model reasoning mode
When it happens
Trigger: Anthropic-style request with thinking disabled against an always-on reasoning model (certain hybrid/always-thinking model configs).
Common situations: Clients that send thinking={"type":"disabled"} by default for cost control; switching a client from a toggleable reasoner to an always-on one.
Related errors
- Anthropic thinking is not supported for models without a rea
- Anthropic thinking is not supported for reasoning parser '{s
- name must be provided
- think_end_token '{reasoning_parser.detector.think_end_token}
- Strict reasoning format requested but the grammar backend do
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/d73c61a068ddab02.
Report an issue: GitHub.