sgl-project/sglang · error · NotImplementedError

deepseek_v4 merges tool messages into user; please preproces

Error message

deepseek_v4 merges tool messages into user; please preprocess with merge_tool_messages()

What it means

deepseek_v4's template merges tool outputs into the following user message; raw 'tool' role messages are not rendered and raise NotImplementedError, telling you to preprocess with merge_tool_messages().

Source

Thrown at python/sglang/srt/entrypoints/openai/encoding_dsv4.py:388

                            if b.get("type") == "text":
                                text_parts.append(b.get("text", ""))
                            else:
                                text_parts.append(f"[Unsupported {b.get('type')}]")
                        tool_content = "\n\n".join(text_parts)
                    parts.append(tool_output_template.format(content=tool_content))
                else:
                    parts.append(f"[Unsupported {block_type}]")
            prompt += "\n\n".join(parts)
        else:
            prompt += content or ""

    elif role == "latest_reminder":
        prompt += LATEST_REMINDER_SP_TOKEN + latest_reminder_msg_template.format(
            content=content
        )

    elif role == "tool":
        raise NotImplementedError(
            "deepseek_v4 merges tool messages into user; please preprocess with merge_tool_messages()"
        )

    elif role == "assistant":
        thinking_part = ""
        tc_content = ""

        if tool_calls:
            tc_list = [
                tool_call_template.format(
                    dsml_token=dsml_token,
                    name=tc.get("name"),
                    arguments=encode_arguments_to_dsml(tc),
                )
                for tc in tool_calls
            ]
            tc_content += "\n\n" + tool_calls_template.format(
                dsml_token=dsml_token,

View on GitHub (pinned to 0132848349)

Solutions

  1. Call merge_tool_messages(messages) before encoding/sending.
  2. Or configure the serving adapter to apply the merge automatically.
  3. Replace tool messages with merged user messages containing <function_results> blocks if merging manually.

Example fix

# before
messages = [{...assistant w/ tool_calls...},{"role":"tool","content":"42"}]
# after
from sglang.srt.entrypoints.openai.encoding_dsv4 import merge_tool_messages
messages = merge_tool_messages(messages)
Defensive patterns

Strategy: fallback

Validate before calling

from sglang.srt.entrypoints.openai.encoding_dsv4 import merge_tool_messages
messages=[m for m in messages if m['role']!='tool'] or merge_tool_messages(messages)

Type guard

def has_raw_tool_role(msgs): return any(m['role']=='tool' for m in msgs)

Prevention

When it happens

Trigger: Sending a messages array containing role='tool' directly to the DSv4 encoder/serving endpoint without calling merge_tool_messages() first.

Common situations: Replaying OpenAI-style tool transcripts verbatim; client frameworks that always emit tool-role messages; missing preprocessing step in a custom integration.

Related errors


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