Skip to content

[Bug] Provider API error 400: TodoList tool result present in wire log but missing from provider context #1195

Description

@Reflexivityofmind

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

  1. Start a new session with a multi-step goal.
  2. 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.
  3. 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.
  4. Turn 0 step 2 completes with finishReason: "tool_use".
  5. Turn 0 step 3 starts. Immediately, the LLM request fails with the 400 error above.
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions