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

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions