Skip to content

Kimi (moonshotai-cn) 400s on replayed tool history: orphaned tool messages, interleaved user messages, duplicate tool_call_id #8537

Description

@wulong-t

What happened?

Replaying a session's history to Kimi (moonshotai-cn, openai-completions, kimi-k2/kimi-k3) fails with 400s that lenient providers never trigger:

  1. Invalid request: messages with role 'tool' must be a response to a preceding message with 'tool_calls'
  2. Invalid request: tokenization failed

Root causes, all in transformMessages:

  • Errored/aborted assistant messages are skipped on replay, but their tool results are kept -> orphaned tool message (error 1).
  • Custom messages (e.g. background-task notifications) interleaved between an assistant tool call and its result serialize as user messages -> tool result follows a user message (error 1).
  • The synthetic "No result provided" inserted for an interrupted tool call remains next to the real result -> two tool messages with the same tool_call_id (error 2).

Steps to reproduce

  1. Use an OpenAI-compatible provider that validates message order, e.g. moonshotai-cn with kimi-k2 or kimi-k3.
  2. In a session, let the model call a tool, then interrupt the turn (abort/error mid tool-call), or use a background-task tool (subagent_wait) whose notification lands before the tool result.
  3. Send a follow-up message. pi replays the history and the API returns the 400 above.

Verified by replaying the exact failing 275-message history against the real Moonshot API: 400 before the fix, HTTP 200 after.

Expected behavior

Replayed history stays structurally valid for every provider: no tool message without a preceding assistant tool_calls message, no user message between tool_calls and its result, no duplicate tool_call_id.

Version

0.84.2


I have a fix and unit tests ready on my fork (wulong-t/pi, branch fix/tool-result-history-normalization); PR #8536 was auto-closed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions