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

  1. Keep reasoning in exactly one place: either reasoning_content or thinking parts
  2. 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

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


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/80bff17fed5e05a8. Report an issue: GitHub.