GitHub Actions: "Cache not found for input keys"
The restore step looked for a cache entry and found none, so the job runs without it. It is not an error, and the step passes. What matters is why nothing matched, and it is usually one of five things.
What it looks like
From a pull request build in October 2026 that took 13 minutes because of it (homeboy #17018):
Cache not found for input keys: Linux-cargo-source-v2-8c1ea9e4…-7eb031de…-8f01ff49…, Linux-cargo-source-v2-8c1ea9e4…-7eb031de…-
- The first key is
key, and the rest arerestore-keys, in order. An entry matches when its key equalskey, or starts with one of the restore keys. - It must also have the same version, a hash that has nothing to do with the key (see 3 below).
1. The key changed
hashFiles()over a file that changes more often than what is cached. In homeboy,Cargo.lockgets new versions of the project's own crates at every release, several a day. In pi-setup #151 the key hashed the whole workflow file, so editing one word of a comment made the next run fetch everything again.- The save step computed a different key from the restore step. In ozone #11665 the restore looked for
maven-repo-d88b…and the save wrotemaven-repo-0bf0…, because by thenhashFiles('**/pom.xml')also matchedpom.xmlfiles the build had written undertarget/. The next run looked ford88b…again. Their fix runsmvn cleanbefore the save.
Hash only the files that decide the contents, leave build output out, save under the key the restore step used, and add a restore key so a near entry is used when the exact one is not there:
- uses: actions/cache/restore@v6
id: restore-cache
with:
path: ~/.m2/repository
key: maven-repo-${{ hashFiles('**/pom.xml', '!**/target/**') }}
restore-keys: maven-repo-
# ... build ...
- uses: actions/cache/save@v6
if: steps.restore-cache.outputs.cache-hit != 'true'
with:
path: ~/.m2/repository
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
2. The entry is in a scope this run cannot read
- A run can restore caches from its own branch and the default branch, and in a pull request, from the base branch too. It cannot restore caches from child or sibling branches, or from a different tag.
- A cache saved in a pull request belongs to
refs/pull/<number>/merge, and only re-runs of that pull request can restore it. A new pull request starts from what the default branch saved. - So if nothing on the default branch saves that key, every pull request misses. In homeboy the default branch's entries had a different key segment from the pull requests' keys. In saboteur #922 the job meant to fill the cache was cancelled before it could save whenever it had something to build.
Let a run on push to the default branch save the entries that pull requests restore, with the same key scheme.
3. Same key, different version
Besides the key, every entry has a version, and a restore only matches the same version, also for restore keys. The toolkit computes it from:
- the
pathlines exactly as written, in order:~/.npmand/home/runner/.npmare different versions; - the compression: a runner or container without
zstduses gzip, and does not find entries saved with zstd; - on Windows, a Windows-only mark, unless
enableCrossOsArchive: trueis set when saving and when restoring.
With step debug logging on, the restore also logs "Cache not found for version <hash> of keys: ...", which you can compare with the versions of the entries that exist (turning on debug logging).
4. The entry was evicted
- GitHub removes entries not used for 7 days. When a repository's caches go over its limit, 10 GB unless changed, the least recently used go first.
- In test-in #430 a 2,910 MB entry saved at 06:48 was gone 33 minutes later, pushed out by 7,030 MB another job saved. Pull request copies count too: in helion #3799 four of them took 6.2 GB of 10.06 GB.
Save fewer and smaller entries, skip the save in pull requests (if: github.event_name == 'push' on the save step), or raise the limit in the repository's Actions settings, which is billed above 10 GB.
5. The download failed
A restore that found the entry but could not download it ends with the same line (helion #3799):
Cache hit for: triton-thirdparty-b200-tileir-0d9283bf49 Received 125829120 of 1547099396 (8.1%), 30.0 MBs/sec ... Failed to restore: The operation cannot be completed in timeout. Cache not found for input keys: triton-thirdparty-b200-tileir-0d9283bf49
Look one line up. "Cache hit for" followed by "Failed to restore" is a download problem, not a missing entry.
Seeing what is there
gh cache list --key maven-repo- --json key,ref,version,lastAccessedAt,sizeInBytes
refis the scope:refs/heads/main, orrefs/pull/123/mergefor one pull request's copy.- An entry with the right key but another
versionis case 3. - No entry at all, though a run saved one, is case 4.
cache-hit is empty on a miss
steps.<id>.outputs.cache-hitis'true'for an exact match,'false'only when a restore key matched, and empty when nothing was restored. The code leaves it unset on purpose, citing actions/cache #1466.- So a step with
if: steps.cache.outputs.cache-hit == 'false'never runs on a full miss. In endjin #233 a check meant to stop the job when its build state was missing never ran, and a release build passed and published nothing. Test!= 'true'instead. - To fail the job when the entry is missing, set
fail-on-cache-miss: true. The step then stops with "Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ...".
Telling it apart
- "Cache restored from key: ..." is a hit. "Cache hit for restore-key: ..." is a partial one, and the save at the end then writes the full key.
- "Failed to save: Unable to reserve cache with key" is the save at the end, not the restore ("Unable to reserve cache").
See failed jobs from IntelliJ IDEA
Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).
GitHub and GitHub Actions are trademarks of GitHub, Inc.; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc. or JetBrains.
More: "Unable to reserve cache" · Debug logging and ACTIONS_STEP_DEBUG · "No space left on device" · GitHub Actions plugins for IntelliJ IDEA compared · 日本語