# GitHub Actions Cache Not Saved After an Exact-Key Hit

> Understand why actions/cache does not save when the exact key already exists - caches are immutable, so a stale exact key prevents updated content from being stored.

Source: https://latchkey.dev/learn/github-actions/gha-cache-not-saved-on-hit  
Updated: 2026-06-25

actions/cache skips the save when an entry already exists for the exact key, because cache entries are immutable. If the content changed but the key did not, the new content is never stored.

## Diagnose it: was the cache hit, and was it the right one?

Cache bugs split into three shapes and they need different fixes: the cache never saved, it saved but the key never matches on restore, or it restored a stale entry through a `restore-keys` prefix and is now poisoning the build. The step output tells you which one you have.

```.github/workflows/ci.yml
- uses: actions/cache@v4
  id: cache
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-npm-

- name: What happened
  run: |
    echo "exact hit: ${{ steps.cache.outputs.cache-hit }}"
    echo "key used:  ${{ steps.cache.outputs.cache-matched-key }}"
```

> `cache-hit` is only `true` on an exact key match. A `restore-keys` prefix match reports `cache-hit: false` while still restoring files, which is exactly how a stale cache gets mistaken for no cache at all.

## Cache limits that produce confusing failures

- Repository cache is capped at 10 GB. Past that, GitHub evicts least-recently-used entries, so a large cache can silently stop persisting.
- Caches are scoped by branch. A cache written on a feature branch is not visible to another feature branch, only to its base and its own descendants.
- An entry not read for 7 days is evicted, so a rarely-run workflow effectively never has a warm cache.
- Restoring a cache built for a different tool version is worse than a cold start, because you get a corrupted tree instead of a clean install. Always include the tool version in the key.

## FAQ

### What causes GitHub Actions cache not saved after an Exact-Key hit?

There are 2 common causes: immutable cache keys and key not reflecting content changes. A cache key maps to one immutable entry.

### How do I fix GitHub Actions cache not saved after an Exact-Key hit?

There are 2 fixes depending on which cause you have: make the key reflect the content and use a rolling key when content changes often. Work through them in order, since the first is the most common.

### What does GitHub Actions cache not saved after an Exact-Key hit actually mean?

The post-job cache step logs that the cache already exists and is not saved, so updated dependencies are never persisted under that key and later runs restore stale content.

### How do I stop GitHub Actions cache not saved after an Exact-Key hit happening again?

Tie the cache key to a hash of the content it stores. The prevention section lists 3 changes that keep it from recurring.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
