GitHub Actions cache-hit Output Ignored - Steps Rerun on a Hit
Expensive setup runs on every job even when the cache was restored, because nothing checks the cache-hit output. The actions/cache cache-hit output is only true for an exact key match, not a restore-keys partial hit.
What this error means
A dependency-install or build step runs in full despite a successful cache restore, wasting time, because the workflow never branched on steps.<id>.outputs.cache-hit.
- id: cache
uses: actions/cache@v4
with: { path: ~/.npm, key: npm-${{ hashFiles('package-lock.json') }} }
- run: npm ci # always runs, even when the cache was restoredCommon causes
cache-hit output never consumed
actions/cache exposes a cache-hit output, but unless a later step reads it, nothing skips the now-redundant work.
Confusing exact-hit with restore-key hit
cache-hit is only true on an exact key match. A restore-keys prefix restore leaves cache-hit false (empty), so a naive equality check misclassifies a partial hit.
How to fix it
Gate work on the cache-hit output
Skip the expensive step when the exact cache was restored.
- id: cache
uses: actions/cache@v4
with: { path: ~/.npm, key: npm-${{ hashFiles('package-lock.json') }} }
- if: steps.cache.outputs.cache-hit != 'true'
run: npm ciAccount for partial restores
- Remember cache-hit is "true" only for an exact key match.
- For restore-keys partial hits, still run a lightweight update step (e.g. npm ci) since the cache may be stale.
- Use the cache-hit boolean to skip only when an exact, complete cache was restored.
How to prevent it
- Branch expensive setup on steps.<id>.outputs.cache-hit.
- Treat restore-keys hits as partial - do not skip updates on them.
- Compare cache-hit against the string "true" explicitly.