Claude Cache Invalidated When Tools or System Change
Your cache was hitting fine, then stopped after a code deploy or tool version bump. Root cause: cache matches by exact byte-level prefix. Any change to system, tools, or content before the breakpoint invalidates the cache — including reordering tools, whitespace changes, or JSON key ordering.
Cache is invalidated by ANY byte-level change to the prefix. Stabilize: sort tools alphabetically, freeze tool JSON schemas at deploy, use canonical JSON serialization for system prompt, and pin content before breakpoints. Version your prompt library — treat prompt changes like schema migrations.
The Symptoms You're Seeing
Cache hit rate: 95% → 0% after deploy at 2026-11-14 15:00 → Something in the prefix changed cache_creation_input_tokens returns nonzero on every request → Fresh cache being written each time = no matching prefix Some traffic hits, some doesn't → Different code paths building slightly different tools/system Cache hits then stops after tool addition → Adding a tool changes the tools array bytes = different prefix After SDK upgrade: cache empty → SDK serialized JSON differently (key order, whitespace)
What Changes Invalidate Cache
| Change | Invalidates? | Notes |
|---|---|---|
| System prompt text | Yes | Even one character |
| Tool added/removed | Yes | Different array = different prefix |
| Tool description edited | Yes | Bytes differ |
| Tool order changed | Yes | Order matters |
| Tool input_schema JSON key order | Yes | Serialization matters |
| Model name changed | Yes | Cache is per-model |
| anthropic-version header | Yes | Part of cache key |
| Whitespace/newlines added | Yes | Bytes differ |
| Adding content AFTER breakpoint | No | Prefix unchanged |
| Reordering messages after breakpoint | No | Prefix unchanged |
What Actually Causes This Silently
Fixes That Work (Tested Nov 2026)
1Canonical Tool Serialization
2Remove Volatile Content From Cached Prefix
Scan your cached prefix for: current time/date, request IDs, session IDs, user personalization data, environment values (staging/prod), feature flags, A/B test variants, version numbers with build hashes. Move any of these to AFTER the breakpoint, or externalize via tools.
3Version-Locked Prompt Registry
Preventing This Error Going Forward
- Canonicalize tools before sending. Sort by name, canonical JSON.
- Remove timestamps from system prompts. Move to user turn or tool.
- Version prompts explicitly. v1/v2/v3 files; upgrade deliberately.
- Log prompt fingerprint. Alert on unexpected changes.
- Test cache hit rate after every deploy. Catch regressions immediately.
- Freeze anthropic-version header. Changing it invalidates all caches.
- Beware SDK upgrades. New serialization = new bytes = cache miss.
Researcher · AI Error Hub
Frequently Asked Questions
Yes. Cache is prefix-match; new tools = different prefix. If you add a tool that's rarely called, consider whether the cost of forcing everyone to re-cache is worth it. Sometimes it's cheaper to run two API surfaces.
Anthropic doesn't expose a "cache probe" endpoint. Best proxy: send a real minimal request and check cache_read_input_tokens. Or maintain a fingerprint log to compare current prompt against last successful cache.
Don't — use tools instead. Tell Claude "call get_current_context() at the start of each conversation." The tool returns timestamp, user data, etc. Cache stays hot; freshness comes from tool call.
Yes. Cache is per-exact-model-identifier. Migrating from claude-sonnet-4-5 to claude-sonnet-4-6 = fresh cache. Plan model migrations with awareness of temporary cost spike.
Yes. Cache is prefix-based, so the exact sequence of messages up to the breakpoint matters. Reordering messages before the breakpoint = new prefix = cache miss. After the breakpoint, no impact on cache.
Related Errors
Keep Your Cache Hit Rate High
Weekly deep dives on prompt versioning, cache observability, and cost tuning. 12,000+ developers subscribe.
Subscribe Free →