Claude Code 2.1.260: The Fable 5.1 Prompt-Cache Bug That Cost Every Tool-Using Agent

Fable 5.1 prompt caching silently excluded post-tool-result context, re-sending it uncached on every tool-call turn. Claude Code 2.1.260 fixes it — along with cache-miss diagnostics, a Read() permission revert, and a managed CLAUDE.md governance change.

Published via Claude Code Changelog

Archive item produced with AI assistance from the cited source and published without individual review. Editor of record: Joe Werner.

Technical diagram showing prompt cache coverage before and after a tool result boundary, with billing tokens highlighted

Claude Code 2.1.260 did not ship new model capabilities. It closed a billing hole that every Fable 5.1 tool-using deployment was falling into since Fable 5.1 launched on September 1.

The specific bug: prompt caching on Fable 5.1 did not cover the context attached after tool results. On every subsequent tool-call turn, that context went back to the API as uncached input tokens. For agents that make frequent tool calls — which is most of them — this compounds quickly. A session that calls twenty tools with a 10K-token system-prompt-and-history block was paying uncached input rates for each of those turns. Fable 5.1 charges $10 per million input tokens at the uncached rate and $0.25 per million at the cached rate, a 40:1 ratio. The fix arrived in 2.1.260, but the window of exposure ran from September 1 to whenever a deployment upgraded.

This is worth naming explicitly: Fable 5.1 was not broken for conversation-only agents. It only affected sessions where tool results are appended to the context. That describes most production coding-agent and API-gateway workflows.

Why tool-result context fell outside the cache boundary

The Anthropic prompt-caching design requires that the cached prefix be stable across turns. Tool results get appended to the message list after each call, which updates the context. The correct behavior is to cache up to the current stable prefix — everything before the new tool result — and charge cached rates for that portion on the next turn. The bug caused the implementation to mark the post-tool-result block as non-cacheable input, so the entire updated context re-billed at full rate on every tool-call round trip.

The cross-provider angle is relevant here because this failure mode is specific to Anthropic's prompt-caching mechanism. OpenAI's API handles tool-result continuation differently — it does not expose an explicit caching boundary the client must track. Operators who run mixed-provider routing, sending some sessions to Anthropic and some to OpenAI, would have seen cost differences between equivalent Fable 5.1 and GPT-5.6 tool-using sessions and possibly attributed it to model price differences rather than a caching defect. The actual billing delta is corrected from this release forward.

For TheRouter deployments with Fable 5.1 enabled: if you log per-turn token breakdowns from the usage field in API responses, you can calculate the exposure window by summing uncached_input_tokens across Fable 5.1 tool-call turns between September 1 and the date you updated to 2.1.260. Turns where cache_read_input_tokens is zero despite a non-empty prior context are the affected turns. The fix applies automatically on upgrade — no configuration change is needed.

/cost now reports why your prompt cache missed

Separately from the bug fix, 2.1.260 adds cache-miss cause annotations to /cost and to the status line's prompt_cache field. The reported causes are: tool definitions changed, system prompt changed, idle past the TTL.

Before this, an operator watching cost anomalies had to compare turn-by-turn API response metadata manually to reconstruct why caching stopped working mid-session. A tool-definition change is a common trigger in managed Claude Code deployments where plugins are pushed to all users: if a plugin update changes the tool schema, the cached prefix is invalidated from that point. An idle-past-TTL miss looks identical in billing logs to a system-prompt change unless you have timestamps to diff.

The operator workflow this enables: run /cost after a suspicious session and check the annotated miss reason before opening a billing dispute. If the cause is tool definitions changed, the investigation starts at the managed settings or plugin push. If it is system prompt changed, the investigation starts at any CLAUDE.md update or runtime injection. If it is idle past TTL, the session had a gap long enough to expire the cache — which for Fable 5.1 is relevant because longer-running coding agents may naturally pause while waiting for human review.

The Read() permission revert that security audits may have missed

2.1.260 reverts a change from 2.1.259. The 2.1.259 change applied Read() deny rules to Bash arguments, which caused npm run build to be denied under a Read(./**/build/**) rule in every mode. The revert removes that behavior.

The security implication runs in both directions. Before 2.1.259, Read() deny rules controlled only file reads, not Bash arguments that happened to reference matching paths. The 2.1.259 change tried to close a gap — a rule that said "don't read from the build directory" would not also stop cd build && grep from running. The revert means that gap is back.

For operators who updated from 2.1.258 to 2.1.259 and then to 2.1.260 in rapid succession, the permission audit is: any Read() deny rules you wrote expecting them to also cover Bash path arguments are no longer enforced that way. A Read(./**/build/**) rule will block file reads from build/, but not a grep -r build/ command. If that distinction matters for your security posture, use explicit Bash() deny rules in addition to Read() deny rules.

The companion fix to watch: 2.1.260 also fixes permissions.blockReadsOutsideWorkingDirectories on macOS hiding a worktree-isolated sub-agent's own checkout. If you run isolated sub-agent worktrees and this setting is enabled, test that agents can read their own checked-out files before deploying the update broadly.

Managed CLAUDE.md no longer requires operator security approval

2.1.260 changes managed settings behavior: a managed CLAUDE.md pushed through claudeMd in server-managed settings no longer triggers the security approval dialog that hooks, shell commands, sandbox rules, and unsafe env entries still require.

For operators who manage Claude Code fleets through server-managed settings and push CLAUDE.md content centrally, this means routine CLAUDE.md updates will not prompt the user for approval before taking effect. Hooks and shell-level rules still require approval. The distinction matters because CLAUDE.md controls agent behavior at the prompt level — what Claude knows about the project, its style preferences, and how it should respond to instructions. That content can steer behavior significantly even without shell access.

The cross-provider context: no equivalent governance layer exists in Claude Code for OpenAI or DeepSeek backends. The approval distinction is specific to the Anthropic-managed-settings stack. If you route some Claude Code sessions through the Anthropic API and others through a non-Anthropic backend, the CLAUDE.md governance change only affects the Anthropic-managed path. The non-Anthropic paths continue to apply CLAUDE.md from the local file in the working directory, with no centralized push or approval flow.

The practical change for operator teams: if your managed CLAUDE.md includes routing hints, model preferences, or behavioral overrides that you previously tested in a staging environment before rollout, the approval step was a natural gate. Without it, the path from managed-settings update to live user session is shorter. Consider logging managed CLAUDE.md deployments separately so the version active during any given session can be retrieved for post-incident review.

oidc.scope_on_refresh for gateway IdPs with non-standard refresh behavior

Claude apps gateway adds oidc.scope_on_refresh to support IdPs that return an id_token on refresh only when the openid scope is explicitly re-requested. This is a narrow fix that matters in exactly one configuration: a Claude apps gateway backed by an IdP where the openid scope is not automatically included in the refresh token request.

The operator consequence: if Claude Code sessions using your gateway were silently degrading from authenticated to unauthenticated state mid-session — particularly long-running coding sessions — and your IdP fits the pattern above, this setting restores the id_token on refresh. Without the id_token, a gateway that validates session identity using OIDC claims will see the claim validation fail on refresh and either reject the session or fall back to anonymous handling depending on your failure policy.

Set oidc.scope_on_refresh: "openid" in your Claude apps gateway config if refresh calls are currently returning a token without the claims your gateway expects. Do not set it if your IdP already includes the scope by default, as it adds a round-trip parameter with no benefit.

Help & contact