Skip to content

BasicTruncator creates orphaned tool_result messages when splitting tool_use/tool_result pairs at truncation boundary #2589

@Overlord-Zurg

Description

@Overlord-Zurg

Describe the bug

When a session hits the token limit and compaction triggers, the BasicTruncator removes messages from the front of the conversation history without accounting for tool_use/tool_result pairs that straddle the truncation boundary. This leaves tool_result blocks in the remaining history with no corresponding tool_use, which causes the Anthropic API to reject the request with:

CAPIError: 400 tool call must have a tool call ID and function name

The session then gets into an unrecoverable loop — every subsequent prompt or manual /compact attempt hits the same error.

Affected version

GitHub Copilot CLI 1.0.21

Steps to reproduce the behavior

Hard to reproduce reliably, but the conditions are:

  1. Run a long session until it approaches the token limit.
  2. A new prompt triggers automatic compaction.
  3. The BasicTruncator removes N messages, where the cut happens to split an
    assistant message (containing tool_use blocks) from its corresponding
    tool.execution_complete results.
  4. The Anthropic API returns 400 "tool call must have a tool call ID and function
    name" during compaction.
  5. Every subsequent prompt or /compact triggers the same failure loop.

Note: though the error message comes from the Anthropic API, the root cause (BasicTruncator not preserving tool_use/tool_result pairs) is model-agnostic and produces a similar error with OpenAI models.

Expected behavior

The truncator should keep tool_use/tool_result pairs together. When removing messages from the front of the history, it should either:
(a) also remove any subsequent tool_result messages belonging to removed tool_use blocks, or
(b) stop the truncation boundary just before a tool_use block so the pair stays intact.

Additional context

OS: Windows
Shell: PowerShell 7
Terminal: Windows Terminal
CPU: x86_64

The session.db and events.jsonl from the broken session show 176 tool_use calls and 176 tool_results total, but after truncation removed 62 messages, 3 tool_result messages were left without their corresponding tool_use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions