Skip to content
Latchkey

CircleCI restore_cache Always Misses - Fix Cache Keys

Your restore_cache never finds a hit, so every run reinstalls dependencies from scratch. The keys are non-deterministic, point at the wrong file, or don’t match what save_cache wrote.

What this error means

Logs show "No cache found for key ..." on every build, and install steps take full time each run. The cache is being saved but never restored because the lookup key differs from the saved key.

job log
restore_cache
  - Searching for cache key: deps-v1-a1b2c3...
  - No cache found for the given key(s)
save_cache
  - Saving cache deps-v1-d4e5f6...

Common causes

A key that changes every run

Embedding {{ .Revision }}, {{ epoch }}, or {{ .BuildNum }} in the key makes it unique per commit/run, so a restore can never match a prior save.

Checksum over a file that is not the lockfile

{{ checksum "package.json" }} changes for unrelated edits; it should checksum the lockfile (package-lock.json, yarn.lock, poetry.lock) that actually pins dependencies.

save and restore keys do not align

If save_cache writes one prefix and restore_cache searches another, or the partial restore keys don’t overlap, the lookup falls through to a miss.

How to fix it

Use a deterministic, lockfile-based key with fallbacks

.circleci/config.yml
steps:
  - restore_cache:
      keys:
        - deps-v1-{{ checksum "package-lock.json" }}
        - deps-v1-
  - run: npm ci
  - save_cache:
      key: deps-v1-{{ checksum "package-lock.json" }}
      paths:
        - ~/.npm

Keep save and restore keys identical

  1. Use the exact same templated key string in save_cache.key and the first restore_cache.keys entry.
  2. Checksum the lockfile, not the manifest.
  3. Bump the static prefix (v1v2) to intentionally invalidate the cache.

How to prevent it

  • Key caches on the lockfile checksum, never on revision/epoch.
  • Mirror the save key as the first restore key, with a prefix fallback.
  • Version the key prefix so you can invalidate on purpose.

Frequently asked questions

What causes "restore_cache key miss"?
Embedding {{ .Revision }}, {{ epoch }}, or {{ .BuildNum }} in the key makes it unique per commit/run, so a restore can never match a prior save.
How do I fix restore_cache key miss?
Use a deterministic, lockfile-based key with fallbacks

Related guides

References

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