sgl-project/sglang · error · ValueError
Inkling thinking parts require role='assistant'
Error message
Inkling thinking parts require role='assistant'
What it means
The Inkling renderer encodes content parts in message order; 'thinking' parts are only meaningful for assistant messages. If a message with role 'tool' contains a thinking part, render_inkling_messages raises this ValueError before encoding.
Source
Thrown at python/sglang/srt/parser/inkling_renderer.py:113
)
for message_index, message in enumerate(message_list):
if message_index == leading_system_count:
append_effort()
role = _expect_role(message)
if role == "tool":
tool_name = str(
message.get("name")
or tool_call_id_to_name.get(message.get("tool_call_id") or "", "")
)
# The MM processor harvests media from tool messages, so coercing content
# to one string would drop images and desync the placeholder count.
tool_parts = list(_iter_render_parts(message.get("content", "")))
if not tool_parts:
tool_parts = [("text", "")] # else the answered tool_call dangles
for kind, text in tool_parts:
if kind == "thinking":
raise ValueError("Inkling thinking parts require role='assistant'")
_append_message(
input_ids,
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"View on GitHub (pinned to 0132848349)
Solutions
- Remove thinking/reasoning parts from tool and user messages
- Move reasoning content into the assistant message's reasoning_content field
Example fix
# before
{"role":"tool","content":[{"type":"thinking","thinking":"hmm"},{"type":"text","text":"42"}]}
# after
{"role":"tool","content":[{"type":"text","text":"42"}]} Defensive patterns
Strategy: validation
Validate before calling
for m in messages:
if m.get("role") != "assistant":
assert not any(isinstance(p, dict) and p.get("type") in ("thinking","reasoning") for p in (m.get("content") or []) if not isinstance(p, str)) Type guard
def no_thinking_in_non_assistant(m):
if m.get("role") == "assistant": return True
c = m.get("content", "")
return isinstance(c, str) or not any(isinstance(p, dict) and p.get("type") in ("thinking","reasoning") for p in c) Prevention
- Only put reasoning in assistant messages
- Validate message shape before sending Inkling conversations
When it happens
Trigger: Sending a tool-role message whose content includes a part with "type":"thinking" or "reasoning" when using an Inkling-format model.
Common situations: Replaying recorded conversations that mixed reasoning parts into tool outputs; client code that attaches thinking parts to every message generically.
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/fe1f9d95ee66ddba.
Report an issue: GitHub.