github / github/copilot-cli

Failed compaction is retried unchanged on every turn: unbounded billed retries, monotonic context growth, no user-visible error

オープン
#4,663 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

area:context-memory area:models
主要言語
Shell
スター
11.2k
フォーク
1.9k
平均マージ
14時間 16分
マージ済み PR(30日)
6

説明

Describe the bug

When a compaction model call fails, the CLI reissues the identical request on essentially every subsequent turn, with no backoff, no fallback, and no reconciliation of the payload that caused the failure. Each retry is a full billed model call, and because nothing is ever reclaimed, currentTokens grows monotonically until the session hits the hard context limit.

The failure is silent. Nothing appears in the transcript; success: false is only visible in session-state/<id>/events.jsonl. From the user's side the session simply "keeps compacting" and burns credits.

This is error-agnostic and therefore outlives any individual compaction bug. I hit it via a deferred-tool 400 on 1.0.81 (see below), which no longer reproduces on 1.0.82, but the retry behaviour itself is unchanged and still applies to the open compaction-400 reports #4519 and #4572.

Evidence

Two sessions on 1.0.81-3, from local events.jsonl:

session compaction_start success failed
A 38 0 38
B 16 0 16

Every attempt returned the same error and the same toolDefinitionsTokens. Context across session A's retries, from session.compaction_start.data:

trigger=threshold  currentTokens=750,933  ->  908,833   (tokenLimit 936,000)

38 consecutive billed calls, 0 tokens reclaimed, ~158k tokens of growth. The client never varied the request between attempts.

The originating error (for context)
compaction model call failed: HostRethrow {
  message: "400 Tool reference '<redacted-mcp-tool>' not found in available tools"
}

The conversation history referenced an MCP tool that was not declared in the tools array sent with the compaction request. This occurred only while tool search / MCP tool deferral was active (toolDefinitionsTokens ~17.5k vs ~74k with the full catalogue).

The 400 itself no longer reproduces on 1.0.82. I ran 8 trials that each matched the failing shape exactly (deferral active, a deferred MCP tool present in history, automatic trigger: threshold compaction at ~160,800/200,000 tokens, toolDefinitionsTokens: 13,347); all 8 compacted successfully. Seven used one MCP server's tool; the eighth used the specific tool named in every original failure. Deferral was forced with toolSearch: true since the server-side flight is not under my control.

This report is about the retry behaviour, not that 400. The retry path is unchanged, and the same unbounded billed retry would follow from any other compaction failure.

Steps to reproduce

Any persistent compaction failure reproduces the retry loop. On 1.0.81-3:

  1. Run a session with an MCP server whose tools are deferred.
  2. Surface and call a deferred MCP tool.
  3. Let the session grow until trigger: threshold compaction fires.
  4. Observe session.compaction_complete with success: false, then the same request reissued on nearly every following turn.

Detect it in any session with:

python3 - <<'PY'
import json,glob,os
for p in glob.glob(os.path.expanduser('~/.copilot/session-state/*/events.jsonl')):
    bad=ok=0
    for line in open(p,encoding='utf-8',errors='replace'):
        if 'compaction_complete' not in line: continue
        try: e=json.loads(line)
        except: continue
        if e.get('type')!='session.compaction_complete': continue
        d=e.get('data') or {}
        if d.get('success') is False: bad+=1
        elif d.get('success') is True: ok+=1
    if bad: print(f"{p.split('/')[-2]} failed={bad} ok={ok}")
PY

Note the type check matters: tool.execution_complete and session.task_complete also carry success: true and appear on lines containing the string compaction_complete, which inflates the success count if you match the raw line.

Expected behavior

A failed compaction should not be retried unchanged and unbounded. Suggested, in order of value:

  1. Back off. Exponential backoff with a cap, and stop retrying after N consecutive identical failures.
  2. Surface it. A visible warning that compaction is failing and why. Today the only signal is credit burn.
  3. Reconcile or fall back. If the payload is structurally rejected, either repair it (for the case above: build tools from the union of the current catalogue and every tool referenced in the history being summarised) or fall back to hard truncation so the session can still reclaim context.

(3) is bug-specific; (1) and (2) are worth having regardless, and would have converted this from an invisible, unrecoverable credit drain into an actionable message.

Workaround

Resuming the session (copilot --resume=<id>) loads the full tool catalogue and lets compaction succeed. Both sessions above recovered this way, reclaiming 471,261 and 567,747 tokens. They were not permanently lost, but nothing in the UI suggests this.

Affected version
GitHub Copilot CLI 1.0.81-3 (retry loop observed)
GitHub Copilot CLI 1.0.82  (originating 400 no longer reproduces; retry path unchanged)
macOS darwin-arm64, model claude-opus-5, contextTier long_context
Related
  • #4519 and #4572 are open compaction/deferred-tool 400s that would still trigger this retry loop.
  • #4506 and #4639 are also compaction loops, but distinct: in those, compaction succeeds and reclaims nothing, or is driven by storage exhaustion. Here compaction hard-fails and is retried unconditionally.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

提供された Python スキャンを session-state//events.jsonl に対して実行し、繰り返し失敗している compaction_complete イベントを調べます。失敗した compaction を再試行する CLI パスを追跡し、同一の失敗が繰り返される場合に回数制限またはバックオフが適用されること、そしてユーザーにクレジットを消費する再試行が黙って行われるのではなく、目に見える警告が表示されることを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
shell
領域
cli
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
52/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。