How to Debug a Cache That Never Hits in GitHub Actions
A cache that never hits almost always means the key changes every run, the path is wrong, or the save step never ran.
When Cache not found for input keys shows on every run, the cause is usually a key that varies each time (a timestamp or github.sha), a path mismatch between save and restore, an OS mismatch, or a save that never happened because the job failed.
Checklist
- Is the key stable? A key with
github.shaor a date changes every run; key on the lockfile instead. - Do the save and restore paths match exactly, including the same
runner.os? - Did the saving run succeed?
actions/cachesaves in a post-step only if the job did not fail early. - Did the first run actually create the cache? The very first run is always a miss.
Workflow
.github/workflows/ci.yml
steps:
- uses: actions/checkout@v4
- id: cache
uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
- run: echo "cache-hit=${{ steps.cache.outputs.cache-hit }}"
- run: npm ciGotchas
- Enable step debug logging (
ACTIONS_STEP_DEBUG=true) to see the resolved key and which entry was restored. - If
hashFilesreturns an empty string, your glob matched no files and the key collapses; check the path.
Related guides
How to Invalidate a Cache in GitHub ActionsInvalidate a GitHub Actions cache by bumping a version prefix in the key, since cache entries are immutable a…
How to Cache Across Matrix Jobs in GitHub ActionsShare a cache across GitHub Actions matrix legs by including the matrix value in the key, so each OS or versi…