Claude CodeでFable 5.1を--resumeするとキャッシュが効かない——コストが跳ね上がる不具合を追った

Claude CodeでFable 5.1を--resumeするとキャッシュが効かない——コストが跳ね上がる不具合を追った

Claude CodeでFable 5.1モデルを--resumeすると、プロンプトキャッシュが毎回書き込み直しになりトークン代が跳ね上がる不具合(#93490)。Opusでは起きない原因、自分で確認する方法、現状の回避策をまとめた。

エンジニアのゆとです。

--resumeは、クラッシュしたセッションや前日の続きを再開するためのフラグだ。地味だけどありがたい機能で、これがあるおかげで「また最初から背景説明」をしなくて済む。

その--resumeが、Fable 5.1を使っているときだけプロンプトキャッシュを毎回無効化している——という報告がGitHub Issue #93490に上がっている。症状はシンプルだ。キャッシュが効いていれば安い「読み込み」で済むはずのトークンが、毎回高い「書き込み」として課金され続ける。長いセッションを--resumeで繋いでいる人ほど影響が大きい。

自分もFable 5.1をよく使うので他人事ではない。公式ドキュメントとIssue上の技術的な検証を突き合わせて、何が起きているのか整理する。

結論から: 何が起きていて、何をすればいいか

項目内容
症状--resumeしたセッションでcache_readが伸びず、cache_creation(=キャッシュ書き込み=高い方)ばかり計上される
対象モデルFable 5.1のみ。同じ--resume操作でもOpusは正常にキャッシュを読み込む
原因セッション開始時のコンテキスト(messages[1])が、新規起動時はcache_control付きのブロック配列で送られるのに対し、--resume時はcache_controlなしのただの文字列に変わって送信されている
コスト影響Issue報告者の実測で、キャッシュ書き込み単価はキャッシュ読み込みの約80倍(1時間TTLの場合)。長いセッションを--resumeするたびにその差額を払っている計算になる
現状の回避策完全な回避策はまだない。実測して被害を把握する、--resumeの頻度を減らす、可能ならOpusに一時的に切り替える、の3択
github.com
[BUG] --resume never hits the prompt cache past the static prefix on Fable 5.1 (opus hits) この記事の一次情報源。has repro済み、2026年9月10日報告

症状: 数字で見るとこうなる

Issue報告者はローカルプロキシでリクエストを直接キャプチャして、新規起動と--resumeの差分を突き合わせている。ヘッドレスモード(claude -p)での実測はこうだ。

call        cache_read   cache_creation
fresh          12887          24383
resume 1       12887          24644
resume 2       12887          24907

cache_read(安い方)は12887で完全に横ばい。一方cache_creation(高い方)は毎回2万トークン超が新規に書き込まれ続けている。--resumeしているのに、実質的には「毎回そこそこの量を初回起動しているのと同じコスト構造」になっている。

インタラクティブモードでも同じ傾向が出ている。

          cache_read   cache_creation
fresh          0            67824
resume        48825         19376

こちらは1回目の--resumeだけを見ると多少キャッシュが効いているように見えるが、報告者によるとヘッドレスで複数回--resumeを繰り返すケースでは書き込みが毎回発生し続ける。手元の長時間セッション(/backgroundでフォークした大きめのセッション)では、読み込み27,000トークンに対して書き込みが385,000トークンという極端な比率になったケースも報告されている。

原因: セッション開始時のコンテキストが「文字列」に変わる

なぜこんなことが起きるのか。報告者がリクエストの中身をバイト単位で比較した結果、最初に差が出るのはmessages[1]——SessionStartフックの出力と# Environmentブロックを運んでいるシステムメッセージだった。

新規起動時はこう送られる。

{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "<26285文字: SessionStartフックの追加コンテキスト + Environmentブロック>",
      "cache_control": { "type": "ephemeral", "ttl": "1h" }
    }
  ]
}

ところが--resumeで同じセッションを再開すると、まったく同じ26285文字の中身が、こう変わる。

{
  "role": "system",
  "content": "<同じ26285文字>"
}

配列に包まれていた1つのテキストブロックが、ただの文字列に変わり、cache_controlごと消えている。ツール定義もシステムプロンプトもmessages[0]まではバイト単位で完全に一致しているのに、ここだけ形が変わる。プロンプトキャッシュは「先頭からどこまで前回と一致しているか」で判定されるので、この時点で一致が途切れ、それ以降がまるごと書き込み直しの対象になる。

さらに興味深いのは、これがFable 5.1だけで起きる点だ。同じ再現手順をOpusで試すと、まったく同じ形の変化(配列→文字列)が起きているにもかかわらず、Opusはキャッシュにヒットし続ける。

model                fresh                resume 1             resume 2
opus       write 25262 / read 10126   write   353 / read 35388   write   264 / read 35741
fable 5.1  write 24378 / read 12887   write 24639 / read 12887   write 24902 / read 12887

コメント欄では、この差の理由としてFable 5.1のドキュメントにある「シンキングブロックより前のターンを変更すると、そのプレフィックス以降が無効化される」という仕様が指摘されている。--resumeによるメッセージ形式の変化を、Fable 5.1側が「過去のターンが書き換えられた」と解釈してプレフィックス一致を打ち切っている、というのがIssue上で最も裏付けの強い仮説だ。Opusは同じ入力の変化を許容する実装になっているため、この問題が表面化しない。

自分のセッションで確認する方法

「自分の使い方でも起きているか」を確認したいなら、--output-format jsonでヘッドレス実行した結果のusageフィールドを見るのが一番早い。

claude -p "同じ質問をもう一度" --output-format json --resume <session-id>

出力されるresult.usageにcache_read_input_tokensとcache_creation_input_tokensが含まれている。前者がほぼ横ばいで後者が--resumeのたびに大きく計上され続けているなら、この不具合の影響を受けている可能性が高い。日常的にコストを追いたい場合はccusageのようなトークン集計ツールで--resume前後の内訳を比較する方法もある。使用量の見方自体は以前まとめたこちらの記事も参考にしてほしい。

Claude Codeの使用量・トークン消費を確認する方法 完全ガイド 2026 — /usageからccusage・ステータスラインまで
Claude Codeの使用量・トークン消費を確認する方法 完全ガイド 2026 — /usageからccusage・ステータスラインまでClaude Codeの使用量をどう確認すればいいか迷ったら読む記事。公式の/usage・/insights・ステータスラインと、サードパーティのccusageをシーン別に整理し、複数クライアント案件を掛け持ちするフリーランス視点での使い分けまで公式ドキュメントベースで解説する。読む →

インタラクティブモードで簡易的に確認したい場合は/costや/contextでも大まかな傾向はつかめるが、キャッシュの読み書きの内訳までは出ないので、正確に切り分けたいならヘッドレスモードでの実測をすすめる。

現状の回避策

Issue自体はまだオープンで、メンテナーからの確定的な修正コメントはついていない(2026年9月11日時点)。今すぐできることは限られる。

1. 影響範囲を実測してから判断する

すべての--resumeが壊滅的に高くつくわけではない。影響が大きいのは、SessionStartフックやCLAUDE.mdの読み込みで# Environmentブロックが大きくなっているプロジェクト、かつ--resumeを頻繁に繰り返す使い方をしている場合だ。まずは上記の方法で自分のセッションのcache_creationの推移を見て、実害があるかどうかを確認するのが先決だ。

2. 影響が大きい作業だけ一時的にOpusへ

長時間の--resumeを繰り返す予定がわかっている作業(大規模リファクタリングを何日にも分けて続ける、など)は、その期間だけ/model opusに切り替えるという選択肢がある。Fable 5.1の応答品質と引き換えにはなるが、この不具合そのものはOpusでは再現していないので、コスト面では確実に回避できる。

/model opus

opusplanのようなモデルエイリアスの扱いに興味があれば、こちらの記事も合わせてどうぞ。

Claude CodeのmodelPickerでOpus Plan Modeが出てこない — 「カバー済み」誤判定バグの原因と回避策
Claude CodeのmodelPickerでOpus Plan Modeが出てこない — 「カバー済み」誤判定バグの原因と回避策settings.jsonのmodelPickerにopusplanを追加しても/modelの選択肢に出ない不具合を、公式ドキュメントとGitHub Issue #89690の検証結果から整理する。読む →

3. --resumeの回数自体を減らす

セッションを細かく--resumeで繋ぎ直すのではなく、1回のセッション内でまとめて作業を進められないか見直すのも手だ。どうしても再開が必要な場合は、/recapで会話を要約してから新規セッションとして始め直す方が、--resumeを重ねるより結果的に安くつくケースもある。ただしこれはこの不具合を直接回避する方法ではなく、影響範囲を小さくする程度の対症療法だと理解しておいたほうがいい。

なぜこれが軽視できないか: コストの桁が違う

コメント欄で報告者が挙げている単価が生々しい。Fable 5.1のキャッシュ読み込みは$0.25/MTokだが、1時間TTLのキャッシュ書き込みは$20/MTokだという。つまり同じトークン量でも、キャッシュが効かず書き込み扱いになるだけで約80倍の単価差が発生する。

「トークン消費を抑える」という文脈では、モデル選択やCLAUDE.mdのスリム化がよく語られるが、プロンプトキャッシュが静かに効かなくなるバグは、そうした工夫を全部帳消しにしかねない規模のインパクトを持つ。日頃からトークン消費の最適化に取り組んでいる人ほど、今回のような「見えないところで前提が崩れている」ケースには注意したい。

Claude Codeのトークン消費を半減させた10の実践テクニック——MAXプランでも油断するとすぐ上限に達する
Claude Codeのトークン消費を半減させた10の実践テクニック——MAXプランでも油断するとすぐ上限に達するClaude Code MAXプランでもトークン消費は無制限ではない。CLAUDE.mdの最適化、/compact活用、Plan Mode、サブエージェント設計など、実測データ付きで節約術を解説。読む →

FAQ

Sonnetでも同じ不具合は起きるか

Issueの検証はOpusとFable 5.1の比較のみで、Sonnetでの再現報告は2026年9月11日時点で確認できていない。Fable 5.1固有の「ターン改変でプレフィックス無効化」という仕様が原因の中心にあるという仮説が正しければ、同様の実装を持つ他モデルでも起こり得るが、現時点では未検証だと理解しておいたほうがいい。

MCPサーバーを使っていない場合も影響を受けるか

受ける。報告者はMCPサーバーなしの最小構成(--strict-mcp-configで空の設定を指定)でも同じ現象を確認している。MCPサーバーを追加している場合はキャッシュ対象のトークン量自体が増えるため、書き込みコストの絶対額はさらに大きくなる。

このバグはいつから存在するか

報告者はClaude Code 2.1.268で初めて計測しており、それより前のバージョンでの挙動は未計測としている。「アップデートで新しく入った不具合か、以前からあったが気づかれていなかっただけか」は現時点では切り分けられていない。

修正されたかどうかはどこで確認できるか

Issue #93490のページを継続してウォッチするのが確実だ。修正が入った場合はアップデートのチェンジログに「prompt cache」または「resume」という単語が入る可能性が高いので、バージョンアップ時にその2語で検索する習慣をつけておくと見逃しにくい。

まとめ

--resumeでFable 5.1のプロンプトキャッシュが効かなくなる不具合は、設定ミスでもTTL切れでもなく、セッション再開時にコンテキストの送信形式が変わってしまうことが原因らしい。厄介なのはエラーも警告も出ないことで、気づかないまま高い方の単価を払い続けている人が一定数いるはずだ。まずは自分のセッションでcache_readとcache_creationの内訳を確認するところから始めて、影響が大きいようなら一時的にOpusへ切り替えるか、--resumeの使い方そのものを見直すことをすすめる。

Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践
Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践Claude Code の --resume フラグと会話履歴管理を徹底解説。クラッシュ後のセッション再開、セッションIDの特定方法、CLAUDE.md を使った状態の永続化、複数セッション並列管理まで実装例付きで解説。読む →
← 記事一覧に戻る