github / github/copilot-cli

Bug: Concurrent sub-agent events corrupt session state — permanent "tool_use ids were found without tool_result blocks" error

未关闭
#2,543 4 条评论 2 个 reaction 已指派 0 人 在 GitHub 查看
area:agents area:sessions
主要语言
Shell
星标
11.2k
派生
1.9k
平均合并
14 小时 16 分钟
30 天内合并 PR
6

描述

## Error

```
CAPIError: 400 messages.N: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_XXXX.
Each `tool_use` block must have a corresponding `tool_result` block in the next message.
```

This error occurs on **every subsequent message** after corruption -- the session is permanently bricked with no built-in recovery mechanism.

## Environment

- **Copilot CLI version:** 1.0.19
- **OS:** Windows 11
- **Model:** Claude Opus 4.6 (1M context)

## Root Cause

When the main conversation launches a sub-agent (via the `task` tool -- e.g., explore, rubber-duck, or general-purpose agents) and continues making tool calls while the sub-agent runs, both conversations write events to the same `events.jsonl` file. The runtime's message reconstruction does not properly separate the two conversations' tool calls when building the API request. The Claude API then rejects the request because `tool_use` blocks appear without matching `tool_result` blocks in the next message.

## Steps to Reproduce

1. Use a **long-lived session** (one that has undergone at least one compaction)
2. Trigger a `task` tool call to launch a **background sub-agent** (explore, rubber-duck, etc.)
3. While the sub-agent runs, **continue interacting** with the main conversation -- for example, `read_agent` with `wait: true` returns a timeout, and then the assistant makes additional tool calls
4. Sub-agent events (`assistant.message`, `tool.execution_start`, `tool.execution_complete`) interleave with main conversation events in `events.jsonl`
5. **Every subsequent message permanently fails** with the `tool_use`/`tool_result` mismatch error

### Key observation

In the corrupted session we analyzed:
- A sub-agent that ran with **no** main conversation events during its execution -- **no corruption**
- A sub-agent that ran with **110+ main conversation events interleaved** -- **19 orphaned tool calls, session permanently broken**

The difference is whether the main conversation was actively producing events while the sub-agent was running.

## Workaround / Repair Steps

There is no built-in recovery. We manually repaired the session by editing `events.jsonl`:

### Diagnosis

1. Opened `~/.copilot/session-state//events.jsonl`
2. Found the last `session.compaction_complete` event (this is where the runtime starts reconstructing the conversation)
3. Indexed all `assistant.message` events with `toolRequests` after the compaction, along with their `tool.execution_start` and `tool.execution_complete` events
4. For each tool call, checked if the gap between `execution_start` and `execution_complete` contained `assistant.message` or `assistant.turn_start` events from a **different `interactionId`** -- this indicates the sub-agent's events were interleaved

### Repair

1. **Backed up** `events.jsonl` to `events.jsonl.bak`
2. **Removed all events** (any type) that referenced any of the problematic tool call IDs -- this covers the main conversation's tool_use, the sub-agent's internal events, hooks, error events, etc.
3. **Cascaded removal** via `parentId` chains -- removed orphaned `hook.start`/`hook.end` and `tool.execution_start`/`tool.execution_complete` events whose parent was removed
4. **Swept for collateral orphans** -- after removal, some tool calls lost their `tool.execution_complete` as collateral damage, leaving a new `tool_use` without a `tool_result`. Iteratively detected and removed these until no orphans remained
5. **Fixed parent chain links** -- updated `parentId` references on surviving `assistant.turn_end` events to point to the nearest surviving ancestor
6. **Removed all `session.error` events** (just repeated failure logs from retries)

A reusable PowerShell repair script is available in [this repair script](https://gist.github.com/KeithIsSleeping/1a919a69a5707b764d880cf9e38e5e70).

## Suggested Fix

The runtime's message reconstruction should filter events by conversation/interaction context before building the Claude API messages array. Sub-agent internal events (`assistant.message`, `tool.execution_start/complete`, `assistant.turn_start/end`) should not be included in the main conversation's messages -- they belong to a separate conversation context.

Alternatively, sub-agent events could be written to a separate events file (e.g., `events..jsonl`) to prevent interleaving entirely.

贡献指南

打开贡献指南

调研方向

Start by examining the session-state//events.jsonl entries after the last session.compaction_complete event, focusing on interleaved interactionId values and tool execution events. Trace how those events become the main conversation's API messages; done means sub-agent events are excluded or isolated so concurrent activity no longer produces orphaned tool_use blocks or permanently corrupts the session.

由索引模型根据 Issue 内容生成。

评估

领域
cli
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
冷清
描述清晰度
基本清楚
新手友好度
45/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。