Skip to content
Latchkey

GitHub Actions cache/restore Never Saves - Missing cache/save Step

A cache never gets populated because the workflow uses actions/cache/restore on its own. The split restore/save actions do not auto-save at job end - only the combined actions/cache does - so you must add a cache/save step.

What this error means

Every run is a cache miss because nothing ever saves the cache. The restore step runs but no corresponding save persists the directory after the build.

.github/workflows/ci.yml
# restore only - cache is never written back
- uses: actions/cache/restore@v4
  with: { path: ~/.npm, key: npm-${{ hashFiles('package-lock.json') }} }
- run: npm ci
# (no actions/cache/save step) -> next run misses again

Common causes

Split restore without save

actions/cache/restore only reads. Unlike the combined actions/cache, it has no post step that saves, so without an explicit save the cache is never written.

Assuming auto-save like the combined action

The combined actions/cache saves automatically at job end. The restore/save split trades that convenience for control, so you own the save step.

How to fix it

Add a matching cache/save step

Save with the same key (often gated on a cache miss) after the build produces the directory.

.github/workflows/ci.yml
- uses: actions/cache/restore@v4
  id: cache
  with: { path: ~/.npm, key: npm-${{ hashFiles('package-lock.json') }} }
- run: npm ci
- if: steps.cache.outputs.cache-hit != 'true'
  uses: actions/cache/save@v4
  with: { path: ~/.npm, key: npm-${{ hashFiles('package-lock.json') }} }

Or use the combined action

  1. Switch to actions/cache when you want automatic restore + save.
  2. Use restore/save split only when you need to control when the save happens.
  3. Keep the save key consistent with the restore key.

How to prevent it

  • Pair every actions/cache/restore with an actions/cache/save.
  • Use the combined actions/cache when you do not need split control.
  • Gate the save on a cache miss to avoid redundant uploads.

Frequently asked questions

What causes "restore without save"?
actions/cache/restore only reads. Unlike the combined actions/cache, it has no post step that saves, so without an explicit save the cache is never written.
How do I fix restore without save?
Save with the same key (often gated on a cache miss) after the build produces the directory.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card