anthropics / anthropics/claude-code

[BUG] Resumed session drops a tool from the parent's initial tools array (EndConversation), so its first request misses the prompt cache

Open
#94,400 0 comments 0 reactions 0 assignees View on GitHub
area:core bug has repro platform:windows
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## What happens

A resumed session (`--resume `, which forks) does not reproduce the parent's tools array when the parent had a server-gated tool, here `EndConversation`, in its tools array from its first request. The fork's first request goes out without that tool and receives it a few seconds later as a `deferred_tools_delta` attachment. The prefix therefore differs early, and the fork's first request misses the prompt cache for the whole conversation, although the cache is well within its TTL.

Tools and system prompt that arrived *after* the parent's first request are restored correctly on resume. Only a tool present in the parent's initial tools array is lost.

## Environment

- Claude Code 2.1.270, Windows 11, background sessions (`claude --bg`)
- `--safe-mode --tools "Bash,PowerShell,Read,Grep,Glob"`, so no ToolSearch and the tool cannot be deferred
- `--model claude-opus-5`, `--max-turns 40`, `--dangerously-skip-permissions`
- All cache writes are 1h (`ephemeral_1h_input_tokens`), so expiry is ruled out

## Steps

1. Start a background session with a restricted `--tools` list that omits ToolSearch, at a moment when the `EndConversation` tool is enabled for the process (it is gated server-side, so this happens in some sessions and not others).
2. Let it finish a turn.
3. About 2 minutes later, resume it: `claude --bg --resume ...` with the same flags.
4. Compare `usage` on the parent's last request and the fork's first request.

## Evidence (one parent and fork pair)

| request | cache_read_input_tokens | cache_creation_input_tokens |
|---|---|---|
| parent, first request (tool in the array) | 8,926 | 7,776 |
| parent, last request | 27,957 | 1,118 |
| fork, first request, 2m11s later | **7,462** | **20,562** |
| a cold session *without* the tool, first request | 7,462 | 7,701 |

- The fork's first read (7,462) equals the static prefix of a session without the tool, so the fork's tools array lacked it.
- 3 s into the fork its transcript has an `attachment` of type `deferred_tools_delta` with `addedNames: ["EndConversation"]`.
- A second parent and fork pair, where the parent never had the tool in its array, resumed 26 s later with a full hit (read 31,790, creation 698). The same machine, flags, worktree handling and version, so forking itself does not break the cache.
- `--disallowedTools EndConversation` does not keep the tool out of the request, so there is no workaround from flags.

## Expected

On resume, the fork's first request should carry the same tools array as the parent's last request, as recorded in the parent's `prompt_snapshot`, so the prefix matches and the cache is read.

## Impact

About 20K tokens written instead of read on the first request of each affected resume. In our automation this is roughly 1 in 5 resumes for sessions started with a restricted tool list. No noticeable latency cost.

One test resume on 2.1.271, with the tool enabled in the parent, got a full hit. That is a single sample, so it may be fixed or it may be the race.

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the resume flow with the restricted --tools list and compare the parent's last request with the fork's first request, including prompt_snapshot and the deferred_tools_delta attachment. Trace resume handling to ensure the fork restores the parent's initial tools array; done means the first resumed request includes EndConversation when it was present in the parent's last request and retains the prompt-cache prefix.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.