{"record":{"id":"24c81d4842d7b74d","repo":"sgl-project/sglang","slug":"thinkingmode-thinking-mode-invalid-message-wit","errorCode":null,"errorMessage":"ThinkingMode: {thinking_mode}, invalid message without reasoning_content/tool_calls `{msg}` after last user message","messagePattern":"ThinkingMode: (.+?), invalid message without reasoning_content/tool_calls `(.+?)` after last user message","errorType":"exception","errorClass":"DS32EncodingError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/entrypoints/openai/encoding_dsv32.py","lineNumber":277,"sourceCode":"        tool_calls_content = \"\"\n        if tool_calls:\n            tool_calls = [\n                tool_call_template.format(\n                    dsml_token=dsml_token,\n                    name=tool_call.get(\"name\"),\n                    arguments=encode_arguments_to_dsml(tool_call),\n                )\n                for tool_call in tool_calls\n            ]\n            tool_calls_content += \"\\n\\n\" + tool_calls_template.format(\n                dsml_token=dsml_token, tool_calls=\"\\n\".join(tool_calls)\n            )\n\n        summary_content = content or \"\"\n\n        if thinking_mode == \"thinking\" and index > last_user_idx:\n            if not (reasoning_content or tool_calls):\n                raise DS32EncodingError(\n                    f\"ThinkingMode: {thinking_mode}, invalid message without reasoning_content/tool_calls `{msg}` after last user message\"\n                )\n            thinking_part = (\n                thinking_template.format(reasoning_content=reasoning_content or \"\")\n                + thinking_end_token\n            )\n\n        prompt += assistant_msg_template.format(\n            reasoning=thinking_part,\n            content=summary_content,\n            tool_calls=tool_calls_content,\n        )\n    else:\n        raise NotImplementedError(f\"Unknown role: {role}\")\n\n    return prompt\n\n","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/entrypoints/openai/encoding_dsv32.py#L259-L295","documentation":"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.","triggerScenarios":"thinking_mode='thinking' with a trailing assistant message lacking both 'reasoning_content' and 'tool_calls' (typical for multi-turn history in reasoning mode).","commonSituations":"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.","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."],"exampleFix":"# before\n{\"role\":\"assistant\",\"content\":\"answer\"}  # after last user msg, thinking mode\n# after\n{\"role\":\"assistant\",\"reasoning_content\":\"...\",\"content\":\"answer\"}","handlingStrategy":"fallback","validationCode":"if thinking_mode=='thinking':\n    for m in messages[last_user_idx+1:]:\n        if m['role']=='assistant' and not (m.get('reasoning_content') or m.get('tool_calls')):\n            m.setdefault('reasoning_content','(none)')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use drop_thinking_messages() preprocessing for plain history in thinking mode.","Persist reasoning_content from prior turns."],"tags":["deepseek","thinking-mode","multi-turn"],"backgroundTag":"thinking-content-missing","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}