sgl-project/sglang · error · DS32EncodingError
ThinkingMode: {thinking_mode}, invalid message without reaso
Error message
ThinkingMode: {thinking_mode}, invalid message without reasoning_content/tool_calls `{msg}` after last user message What it means
In thinking mode, every message after the last user message must carry reasoning_content or tool_calls. The DSv32 encoder raises this when a post-user message (e.g. an assistant summary) has neither field.
Source
Thrown at python/sglang/srt/entrypoints/openai/encoding_dsv32.py:277
tool_calls_content = ""
if tool_calls:
tool_calls = [
tool_call_template.format(
dsml_token=dsml_token,
name=tool_call.get("name"),
arguments=encode_arguments_to_dsml(tool_call),
)
for tool_call in tool_calls
]
tool_calls_content += "\n\n" + tool_calls_template.format(
dsml_token=dsml_token, tool_calls="\n".join(tool_calls)
)
summary_content = content or ""
if thinking_mode == "thinking" and index > last_user_idx:
if not (reasoning_content or tool_calls):
raise DS32EncodingError(
f"ThinkingMode: {thinking_mode}, invalid message without reasoning_content/tool_calls `{msg}` after last user message"
)
thinking_part = (
thinking_template.format(reasoning_content=reasoning_content or "")
+ thinking_end_token
)
prompt += assistant_msg_template.format(
reasoning=thinking_part,
content=summary_content,
tool_calls=tool_calls_content,
)
else:
raise NotImplementedError(f"Unknown role: {role}")
return prompt
View on GitHub (pinned to 0132848349)
Solutions
- Use thinking_mode='chat' for plain multi-turn conversations.
- Populate reasoning_content (can be a short placeholder) on post-user assistant messages.
- Use drop_thinking_messages()/the provided preprocessing to strip or fix history before encoding.
Example fix
# before
{"role":"assistant","content":"answer"} # after last user msg, thinking mode
# after
{"role":"assistant","reasoning_content":"...","content":"answer"} Defensive patterns
Strategy: fallback
Validate before calling
if thinking_mode=='thinking':
for m in messages[last_user_idx+1:]:
if m['role']=='assistant' and not (m.get('reasoning_content') or m.get('tool_calls')):
m.setdefault('reasoning_content','(none)') Prevention
- Use drop_thinking_messages() preprocessing for plain history in thinking mode.
- Persist reasoning_content from prior turns.
When it happens
Trigger: thinking_mode='thinking' with a trailing assistant message lacking both 'reasoning_content' and 'tool_calls' (typical for multi-turn history in reasoning mode).
Common situations: Sending plain multi-turn history to a thinking-mode model; clients that drop reasoning_content to save tokens; upgrading a chat flow to thinking mode without regenerating history.
Related errors
- Invalid thinking_mode `{thinking_mode}`
- sparse_attn_v4_paged_decode expects fp16/bf16 q, got {q.dtyp
- bad compress_ratio {compress_ratio}
- Unsupported d_qk: {d_qk}. Expected {DSV4_D_QK} (DeepSeek V4)
- DeepSeekV4 only supports interleave CP strategy, got {cfg.cp
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/24c81d4842d7b74d.
Report an issue: GitHub.