sgl-project/sglang · error · ValueError
assistant message cannot mix reasoning_content with ordered
Error message
assistant message cannot mix reasoning_content with ordered thinking parts
What it means
An assistant message may carry reasoning through either the top-level reasoning_content string OR ordered 'thinking' content parts, but not both — combining them would duplicate reasoning in the rendered transcript. If both are present, the renderer raises ValueError.
Source
Thrown at python/sglang/srt/parser/inkling_renderer.py:134
tokenizer,
"tool",
kind,
text,
author_name=tool_name,
)
continue
parts = list(_iter_render_parts(message.get("content", "")))
turn_start = len(input_ids)
if role == "assistant":
reasoning_content = message.get("reasoning_content")
if reasoning_content:
if not isinstance(reasoning_content, str):
raise TypeError(
"assistant reasoning_content must be a string for Inkling rendering"
)
if any(kind == "thinking" for kind, _ in parts):
raise ValueError(
"assistant message cannot mix reasoning_content with ordered thinking parts"
)
_append_message(
input_ids,
tokenizer,
"assistant",
"thinking",
reasoning_content,
)
for kind, text in parts:
if kind == "thinking" and role != "assistant":
raise ValueError("Inkling thinking parts require role='assistant'")
_append_message(input_ids, tokenizer, role, kind, text)
if role == "assistant":
for tool_call in message.get("tool_calls") or []:
name, args = _tool_call_name_and_args(tool_call)View on GitHub (pinned to 0132848349)
Solutions
- Keep reasoning in exactly one place: either reasoning_content or thinking parts
- Strip reasoning_content when the assistant message content already includes thinking parts
Example fix
# before
{"role":"assistant","reasoning_content":"think...","content":[{"type":"thinking","thinking":"think..."},{"type":"text","text":"ans"}]}
# after
{"role":"assistant","content":[{"type":"thinking","thinking":"think..."},{"type":"text","text":"ans"}]} Defensive patterns
Strategy: validation
Validate before calling
for m in messages:
if m.get("reasoning_content") and isinstance(m.get("content"), list):
assert not any(isinstance(p, dict) and p.get("type") in ("thinking","reasoning") for p in m["content"]) Prevention
- Pick one canonical field for reasoning in stored transcripts
- Strip reasoning_content when content already has thinking parts
When it happens
Trigger: Sending {"role":"assistant","reasoning_content":"...","content":[{"type":"thinking","thinking":"..."}, ...]} in conversation history.
Common situations: Clients that merge model output back into both fields when recording multi-turn conversations.
Related errors
- Inkling reasoning_effort must not be a boolean
- Inkling reasoning_effort must be in [0.0, 0.99]
- invalid Inkling reasoning_effort: {value!r}
- SGLANG_INKLING_DEFAULT_REASONING_EFFORT must be numeric
- SGLANG_INKLING_DEFAULT_REASONING_EFFORT must be in [0.0, 0.9
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/80bff17fed5e05a8.
Report an issue: GitHub.