GitHub Actions:「Failed to save: Unable to reserve cache with key」
ジョブの終わりのキャッシュの保存が行われず、ジョブ自体は成功のままです。この行は GitHub の actions toolkit のキャッシュのパッケージが出すもので、actions/cache も、setup-node・setup-go・setup-uv などに組み込みのキャッシュも、これを使っています。同じ書き出しのあとに2通りの終わり方があり、意味が違います。
2つの行
Failed to save: Unable to reserve cache with key <key>, another job may be creating this cache.そのキーのエントリがもうあるか、別のジョブがいま保存しています。エントリは置き換えられません。GitHub のドキュメントには、既存のキャッシュの中身は変えられず、新しいキーで新しいキャッシュを作る、とあります。actions/cacheでは、これは警告ではなく、ふつうのログの行です。Failed to save: Unable to reserve cache with key <key>. More details: cache write denied: token has no writable scopes(警告)。この実行には、復元しかできないキャッシュのトークンが渡されています。GitHub は2026年6月26日から、書き込み権限の無い人でも起こせるイベントで始まった実行に、こうしています。
キーがもうある
2026年10月28日、pymovements の main への push から(これを止めるプルリクエストは pymovements #1788):
Run actions/cache/save@v4 ... [command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/pymovements/pymovements --files-from manifest.txt --use-compress-program zstdmt Failed to save: Unable to reserve cache with key test-ubuntu-latest-py3.13-4ec5...c7b4, another job may be creating this cache. ##[warning]Cache save failed.
- 2つ目の警告は
actions/cache/save@v4だけです。v5 からは、保存のステップは1行目に何も足しません。 - キーを確保する前にアーカイブを作るので、ジョブはキャッシュ全体を圧縮してから捨てています。先にキーを確かめる変更が actions/toolkit #2550 と #2556 で提案されていて、まだ取り込まれていません。
matlab-actions/run-buildは、失敗の直後に「Cache saved with key」と出します(run-build #91)。何も保存されていません。
よくある出どころ:
- 同じキーのマトリックスのジョブ。キーに入っていない値をマトリックスが変えているので、どのジョブも復元で外れ、みな保存しようとして、1つだけが勝ちます。schemachange #475 では、setup-uv のキーに Python のバージョンは入っていましたが、マトリックスはテストのシナリオも変えていたので、Python のバージョンごとに3つのジョブが競っていました。
- 同じセットアップのステップを持つ2つのジョブ。Web のジョブと E2E のジョブの両方で
setup-nodeにcache: pnpmを付けると、同じキーになります(grounded-expungement-eligibility-agent #110)。 - 毎回動く、別立ての
actions/cache/saveのステップ。そのキーを1回保存したあとは、毎回こうなります(上の pymovements #1788)。 - 変わらないキー(
hashFiles()が入っていない)は1回だけ保存されます。そのあとは保存のたびにこうなるか、actions/cacheが「Cache hit occurred on the primary key ..., not saving cache.」と出し、キャッシュは最初に保存したときの中身のままです。
ジョブどうしが同じファイルを保存するなら、害はありません。勝ったジョブが保存し、あとの実行はそれを復元します。害があるのは、1つのキーの下でジョブごとに違うファイルを作るとき、たとえば同じ OS でコンパイラーを変えるマトリックスです。ほかのジョブは別の設定で作ったファイルを復元するので、そのマトリックスの値をキーに入れます。
止め方
復元で外れたときだけ保存し、キーは中身を決めるファイルから作ります:
- uses: actions/cache/restore@v6
id: cache-restore
with:
path: ~/.cache/pip
key: pip-${{ runner.os }}-${{ hashFiles('requirements*.txt') }}
restore-keys: pip-${{ runner.os }}-
# ... install and test ...
- uses: actions/cache/save@v6
if: steps.cache-restore.outputs.cache-hit != 'true'
with:
path: ~/.cache/pip
key: ${{ steps.cache-restore.outputs.cache-primary-key }}
- ジョブどうしでキーが同じマトリックスなら、1つのジョブにだけ保存させ、ほかは復元だけにします。
actions/cacheなら、保存のステップのif:にマトリックスの条件を足します。setup-uv なら、schemachange はsave-cache: ${{ matrix.scenario-name == 'basics_demo' }}にしました。 - 2つのジョブがどちらもセットアップのアクションのキャッシュを使うなら、片方にだけキャッシュを残し、もう片方では同じパスとキーで
actions/cache/restoreを使うか、ジョブごとにキーの頭を変えます。
この実行は復元しかできない
2026年10月11日、pull_request_target の実行から(sc4pac-actions #12):
##[warning]Failed to save: Unable to reserve cache with key sc4pac-download-cache-80c6c006f143. More details: cache write denied: token has no writable scopes
- 同じログの「Set up job」の部分に
Cache mode: readとあります。保存できる実行ではCache mode: writeです。provider-github #67 の、Issue のコメントで始まった実行にも、同じCache mode: readが出ていました。 - 既定では、デフォルトブランチのスコープにキャッシュを作ったり置き換えたりできるのは
push・workflow_dispatch・repository_dispatch・delete・registry_package・page_build・scheduleだけです。デフォルトブランチで動くほかのイベント、たとえばpull_request_target・issue_comment・workflow_runは、そのキャッシュを復元できますが、保存はできません。pull_requestは対象外です。そのキャッシュはプルリクエストのマージ用の ref に属します。 - 復元はいままでどおり動くので、その実行のために何も保存されていなければ遅くなる、というだけです。
GitHub が勧めていること:
- 信頼できるワークフロー、たとえばデフォルトブランチへの
pushで動くビルドに、キャッシュを満たしておいてもらいます。もう一方のワークフローは、それが保存したものを復元します。 - 信頼の低いワークフローでは
actions/cache/restoreで復元だけにして、警告の出る保存の失敗をなくします。ジョブにcache-mode: readと書けば、同じことがワークフローの上でもはっきりします。 - ジョブに
cache-mode: writeと書くとまた保存でき、実行には、安全な既定を上書きしている、という警告が出ます。GitHub のドキュメントは、これでキャッシュの汚染(信頼できないコードが保存したキャッシュを、権限の強いワークフローがあとで復元する)の危険が戻る、と注意しています。保存より前にフォークやプルリクエストのコードを動かさないジョブにだけ使います。
jobs:
test:
runs-on: ubuntu-latest
cache-mode: read # read, write, write-only or none
steps:
- uses: actions/cache/restore@v6
with:
path: ~/.cache/pip
key: pip-${{ runner.os }}-${{ hashFiles('requirements*.txt') }}
ドキュメントには、キャッシュのストレージに設けた予算をリポジトリが超えたときも、支払いが片づくか、使用量が無料の 10 GB を下回るまで、キャッシュは読み取り専用になる、ともあります。
見分け方
- 「Cache not found for input keys: ...」は、復元のステップが何も見つけなかったという意味です。エラーではなく、キャッシュを満たすのは終わりの保存です。
- 「Resource not accessible by integration」:別の、読み取りしかできないトークンの話で、権限の足りない実行の
GITHUB_TOKENです(「Resource not accessible by integration」)。
失敗したジョブを IntelliJ IDEA から見るなら
Pipeline Inbox for GitHub Actions Workflows は、Lesstep が作っている JetBrains IDE(2024.1 以降)のプラグインです。すべてのリポジトリの実行を、ジョブ・ステップと一緒に IDE のツールウィンドウに並べ、いまのブランチの実行はステータスバーに出ます。読むのは無料、失敗したジョブの再実行・キャンセル・ワークフローの実行・デプロイのレビューは Pro(月 US$1.50・30日の無料試用つき)です。
GitHub と GitHub Actions は GitHub, Inc. の商標、IntelliJ IDEA は JetBrains s.r.o. の商標です。このページは GitHub, Inc.・JetBrains のいずれとも提携しておらず、承認も受けていません。
ほかに:「Unexpected input(s)」の警告 · 「Artifact storage quota has been hit」 · 「Input required and not supplied」 · 「Cache not found for input keys」 · IntelliJ IDEA で使える GitHub Actions のプラグインの比較 · English