Claude Codeの2つのキャッシュバグ、APIコストを最大20倍に膨張させる恐れ
AnthropicのAIコーディングアシスタント「Claude Code」に、プロンプトキャッシュを無効化し、APIコストを静かに10〜20倍に膨らませる可能性のある2つの独立したバグが報告された。Redditユーザーがスタンドアロンバイナリをリバースエンジニアリングした結果、発見したものだ。
バグ1:スタンドアロンバイナリのセンチネル置換によるキャッシュ破壊
Claude Codeのスタンドアロンバイナリ(claude.ai/install.sh や npm install -g で取得するもの)には、AnthropicがカスタマイズしたBunフォークにネイティブ層の文字列置換処理が組み込まれている。この処理は、ZigのHTTPヘッダービルダー関数に注入されており、APIリクエストのJSONボディ内に含まれる課金帰属センチネル(cch=a9ffd)を特定し、ボディのハッシュ値から導出した5文字の16進数で置換する。
問題となるのは、この置換がJSONボディ内の最初の出現箇所を対象とする点だ。シリアライズされたJSONでは messages[] が system[] より先に来るため、会話履歴にセンチネル文字列が含まれている場合(例:Claude Codeのソースコードについて話し合っている、CLAUDE.md にセンチネルが含まれているなど)、system[0] ではなく messages[] 内のセンチネルが置換されてしまう。これによりリクエストごとにメッセージの内容が変化し、キャッシュのプレフィックスが壊れ、毎回フルキャッシュの再構築が発生する。コンテキストサイズに応じて、1リクエストあたり約0.04〜0.15ドルの追加コストが生じる計算だ。
回避策: スタンドアロンバイナリの代わりに npx @anthropic-ai/claude-code で実行することで問題を回避できる。置換処理はカスタムBunフォークにのみ存在し、標準的なNode/Bun上で動くnpmパッケージには含まれていないことが実験的に確認されている。
バグ2:--resume オプションが常にキャッシュミスを引き起こす(v2.1.69以降)
もう1つのバグは、セッション再開を行う --resume オプションに関するものだ。v2.1.69で導入された deferred_tools_delta(ToolSearch経由で利用可能なツールを列挙するシステムリマインダー)の実装の違いにより、再開時に毎回会話履歴全体のキャッシュミスが発生する。
新規セッションでは約13KBのリマインダー群が messages[0] に注入されるのに対し、再開時には messages[0] に約352Bのコンテキストのみが含まれ、リマインダー群は末尾(messages[N])に追加される。この構造の違いにより、キャッシュプレフィックスの不一致、課金ハッシュの変化、cache_control ブレークポイントの位置ズレという3つの独立した要因でキャッシュが破壊される。再開後の2ターン目以降は正常にキャッシュが機能するため、被害は最初のリクエストに限られるが、コンテキストが大きい場合のコストインパクトは無視できない。
このバグはv2.1.68には存在せず、deferred_tools_delta の導入と同時に発生した。現時点で外部から適用できる回避策はない。
日本のユーザーへの影響
Claude Codeは日本でも多くの開発者が利用しており、特にAPIコスト管理を重視するチームや個人開発者にとって見過ごせない問題だ。Anthropicの公式対応を待ちながら、スタンドアロンバイナリを使用している場合は npx 経由への切り替えを検討したい。--resume については正式な修正リリースを待つしかない状況だが、バグ報告のIssue(#40524、#34629)は既に公開されており、Anthropic側も認識していると見られる。