[BUG] Loading a tool for the first time mid-session (e.g. skill, MCP, tool-search) invalidates cache

Status Open
Reported on v2.1.197
Maintainer reply None cached
Activity 4 comments · opened Jul 7, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet (closest are #42309, #44045, #41930, but those are about --resume/billing-sentinel, not mid-session tool loading)
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

Every first-time tool load in a session = a full cache miss on the next turn.

The tools array is the first block in the request so it's right at the front of the cache prefix, which means the second it grows everything after it is invalid. I know tools load lazily, I just figured a new one gets tacked onto the end, not nuke the cache for the whole conversation.

Caught it with an MITM proxy on /v1/messages:

| Turn | Trigger | tools size | cache_read | cache_creation |
|---|---|---|---|---|
| ~37 | first TodoWrite use | 13 → 14 | 84,858 -> 0 | 120,845 |
| ~57 | invoked an MCP-backed skill (loaded 3 MCP tools) | 14 → 17 | 128,716 -> 0 | 150,796 |

That second row is ~150k tokens re-encoded in one turn, around $3 at Fable's cache-write rate.

What Should Happen?

Adding a tool mid-session shouldn't re-encode the whole conversation. Easiest fix is probably to just declare the deferred tools at session start so the array never grows. If that's not doable, warn the user before it invalidates the cache, the way the CLI already does when you resume a conversation past its TTL.

Error Messages/Logs

N/A

Steps to Reproduce

  1. Use a config where tools load lazily (default in recent versions: deferred tool-search on, an MCP server or a skill installed).
  2. Start a session and work until the conversation is large (e.g. ~100k+ tokens).
  3. Trigger a first-time tool load this session, e.g. invoke a skill that pulls in MCP tools, or use an MCP / deferred tool you haven't used yet this session.
  4. Inspect that single turn's API usage. cache_read_input_tokens will collapse to 0 while cache_creation_input_tokens will balloon to your conversation size for that turn.

Claude Model

The bug is model-independent

Is this a regression?

I don't know, this appears to be inherent to lazy tool loading, not a recent change.

Last Working Version

N/A

Claude Code Version

2.1.197, VS Code Extension

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code Extension

Additional Information

This is on Claude Code, not the API. It's growing the tools array lazily mid-session instead of declaring everything up front.

Not the same as the --resume stuff in #42309 / #44045 either, mine is one continuous session, no resume. #42309 says the deferred-tools/MCP/skill caching behavior is undocumented, so here's a real number for it.

View original on GitHub ↗

4 Comments

mayank609 · 1 month ago

@oakif One way to make these issues easier to debug is to capture a complete execution trace of the session - tool registrations, MCP initialization, cache state changes, context mutations, and model/tool transitions. That makes it much easier to pinpoint exactly where the cache became invalid instead of debugging from logs alone.

oakif · 1 month ago

@mayank609 Thanks, that's actually how I caught this. I ran a small MITM forward proxy in front of api.anthropic.com routed through HTTPS_PROXY instead of ANTHROPIC_BASE_URL. It dumps every request body along with the response's usage numbers to a log. That way I can byte diff two subsequent requests to see what differed.

That's also how I got the trace behind the numbers in my original post. I can write up the setup if it'd help, it's a pretty small script.

oakif · 1 month ago

I'd like to comment on another cache miss that I experienced. This one is clearer than the previous one. The session itself is was 13 lines long when this happened. One ToolSearch call in and the cache was invalidated; this was even without a usable tool in the search result.

Please have a look at the screenshot below at the mid-session cache invalidation.

<img width="414" height="597" alt="Image" src="https://github.com/user-attachments/assets/7e1345f5-574b-4cf4-9f53-29898e74326c" />

I asked how to add an email to a TestFlight tester list. ToolSearch ran on the string "testflight tester add beta" and matched 10 unrelated tools. The final answer from Sonnet ended up being "there's no tool for this, go use App Store Connect directly" but still was associated with a cache invalidation.

It looks like ToolSearch can (un)reliably break prompt caching, despire the claims about ToolSearch on the website.

r-aristov · 17 days ago

Confirming instance, captured while isolating a different cache bug (#86299):

Two adjacent turns of the same live session (bare claude-agent-sdk client, setting_sources=[], no skills involved): the tools array (97,767 bytes serialized) diverges at offset 72,055 — WaitForMcpServers appears in turn 2 that wasn't in turn 1. cache_read drops to 0, full prefix re-written.

So this isn't only skill/MCP lazy-loading on first use — internal tools also join the array between turns with no user action at all. Same failure applies across process restarts: if the deferred-tools state differs at resume, the whole session cache is dead from the tools block (this masked #86299 in our first measurements).

Captured request bodies available via a logging proxy on ANTHROPIC_BASE_URL — happy to attach diffs if useful.