Bug Description
Kimi Code fails permanently with a provider API 400 error after a TodoList tool call. The error claims the assistant message containing tool_calls is missing the corresponding tool response, even though the tool result is present in the local wire log.
This appears to be another instance of the corrupted tool-call/tool-result pairing issue described in #705, but reproduced during normal step progression (not session resume or turn.steer), and with the TodoList tool instead of Read.
Error Message
400 an assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: TodoList:3
Error code: provider.api_error, retryable: false.
Environment
- Kimi Code version: 0.20.1
- Install source: homebrew
- OS: macOS 15.5 (Darwin 25.5.0 arm64)
- Shell: /bin/bash
- Model: kimi-code/kimi-for-coding
- Wire protocol version: 1.4
- Session ID: session_a91036c0-be65-4e36-be1d-cb310850bac7
- Workspace: /Users/changlesong/Github/xs-manager
Reproduction / Observed Behavior
- Start a new session with a multi-step goal.
- In turn 0 step 1, the model invokes three
Skill tools in parallel (codex-orchestrate, claude-orchestrate, verification-before-completion). All three return tool.result successfully.
- In turn 0 step 2, the model invokes
TodoList (toolCallId TodoList:3). The tool executes successfully and the tool.result is written to wire.jsonl and server events.
- Turn 0 step 2 completes with
finishReason: "tool_use".
- Turn 0 step 3 starts. Immediately, the LLM request fails with the 400 error above.
- The user sends "继续" (continue). Turn 1 step 1 starts and fails with the exact same 400 error.
The session is bricked: the inconsistent context is persisted and survives across turns.
Key Evidence
From ~/.kimi-code/server/events/session_a91036c0-be65-4e36-be1d-cb310850bac7.jsonl:
{"type":"tool.call.started", "turnId":0,"toolCallId":"tool_1s445pegNXgJ83MF5V4zg4gk","name":"TodoList", ...}
{"type":"tool.result", "turnId":0,"toolCallId":"tool_1s445pegNXgJ83MF5V4zg4gk","output":"Todo list updated...", ...}
{"type":"turn.step.completed","turnId":0,"step":2, ...}
{"type":"turn.step.started", "turnId":0,"step":3, ...}
{"type":"turn.step.interrupted","turnId":0,"step":3,"reason":"error","message":"400 an assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: TodoList:3"}
From ~/.kimi-code/sessions/wd_xs-manager_cbda8dec811e/session_a91036c0-be65-4e36-be1d-cb310850bac7/agents/main/wire.jsonl:
{"type":"context.append_loop_event","event":{"type":"tool.call",...,"toolCallId":"TodoList:3","name":"TodoList",...}}
{"type":"context.append_loop_event","event":{"type":"tool.result",...,"toolCallId":"TodoList:3",...}}
{"type":"context.append_loop_event","event":{"type":"step.end",...,"step":2,...}}
{"type":"context.append_loop_event","event":{"type":"step.begin",...,"step":3,...}}
{"type":"goal.update","status":"paused","reason":"Paused after provider API error: 400 ... TodoList:3"}
The tool.result for TodoList:3 exists locally, but the provider-visible message sequence constructed for step 3 is missing the matching tool message.
Root Cause Hypothesis
The runtime failed to include the TodoList:3 tool result in the message history sent to the provider when starting turn 0 step 3. Because the corrupted history is persisted, subsequent turns (including the user's "继续") keep hitting the same validation error.
In this case there was no turn.steer injection and no explicit session resume between the tool call and the failure; the mismatch happened during normal step-to-step progression. This suggests the context reconstruction / projection logic that builds the provider message list can drop tool results independently of background-task or resume events.
Expected Behavior
- Every
assistant message containing tool_calls must be followed by the matching tool messages before the request is sent to the provider.
- If the runtime detects an orphaned
tool_call (e.g., local tool.result exists but is not included in the projected context), it should repair or drop the pair rather than sending malformed history.
- A session should recover after a user continues from a paused goal, instead of re-emitting the same corrupted context.
Related Issues
Debug Artifacts
Local paths (not uploaded):
~/.kimi-code/server/events/session_a91036c0-be65-4e36-be1d-cb310850bac7.jsonl
~/.kimi-code/sessions/wd_xs-manager_cbda8dec811e/session_a91036c0-be65-4e36-be1d-cb310850bac7/agents/main/wire.jsonl
~/.kimi-code/sessions/wd_xs-manager_cbda8dec811e/session_a91036c0-be65-4e36-be1d-cb310850bac7/state.json
Happy to upload a debug zip or provide additional logs if useful.
Bug Description
Kimi Code fails permanently with a provider API 400 error after a
TodoListtool call. The error claims the assistant message containingtool_callsis missing the corresponding tool response, even though the tool result is present in the local wire log.This appears to be another instance of the corrupted tool-call/tool-result pairing issue described in #705, but reproduced during normal step progression (not session resume or
turn.steer), and with theTodoListtool instead ofRead.Error Message
Error code:
provider.api_error,retryable: false.Environment
Reproduction / Observed Behavior
Skilltools in parallel (codex-orchestrate,claude-orchestrate,verification-before-completion). All three returntool.resultsuccessfully.TodoList(toolCallIdTodoList:3). The tool executes successfully and thetool.resultis written towire.jsonland server events.finishReason: "tool_use".The session is bricked: the inconsistent context is persisted and survives across turns.
Key Evidence
From
~/.kimi-code/server/events/session_a91036c0-be65-4e36-be1d-cb310850bac7.jsonl:{"type":"tool.call.started", "turnId":0,"toolCallId":"tool_1s445pegNXgJ83MF5V4zg4gk","name":"TodoList", ...} {"type":"tool.result", "turnId":0,"toolCallId":"tool_1s445pegNXgJ83MF5V4zg4gk","output":"Todo list updated...", ...} {"type":"turn.step.completed","turnId":0,"step":2, ...} {"type":"turn.step.started", "turnId":0,"step":3, ...} {"type":"turn.step.interrupted","turnId":0,"step":3,"reason":"error","message":"400 an assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: TodoList:3"}From
~/.kimi-code/sessions/wd_xs-manager_cbda8dec811e/session_a91036c0-be65-4e36-be1d-cb310850bac7/agents/main/wire.jsonl:{"type":"context.append_loop_event","event":{"type":"tool.call",...,"toolCallId":"TodoList:3","name":"TodoList",...}} {"type":"context.append_loop_event","event":{"type":"tool.result",...,"toolCallId":"TodoList:3",...}} {"type":"context.append_loop_event","event":{"type":"step.end",...,"step":2,...}} {"type":"context.append_loop_event","event":{"type":"step.begin",...,"step":3,...}} {"type":"goal.update","status":"paused","reason":"Paused after provider API error: 400 ... TodoList:3"}The
tool.resultforTodoList:3exists locally, but the provider-visible message sequence constructed for step 3 is missing the matching tool message.Root Cause Hypothesis
The runtime failed to include the
TodoList:3tool result in the message history sent to the provider when starting turn 0 step 3. Because the corrupted history is persisted, subsequent turns (including the user's "继续") keep hitting the same validation error.In this case there was no
turn.steerinjection and no explicit session resume between the tool call and the failure; the mismatch happened during normal step-to-step progression. This suggests the context reconstruction / projection logic that builds the provider message list can drop tool results independently of background-task or resume events.Expected Behavior
assistantmessage containingtool_callsmust be followed by the matchingtoolmessages before the request is sent to the provider.tool_call(e.g., localtool.resultexists but is not included in the projected context), it should repair or drop the pair rather than sending malformed history.Related Issues
Read:158, including detailed root-cause analysis and related PRs.Debug Artifacts
Local paths (not uploaded):
Happy to upload a debug zip or provide additional logs if useful.