GitHub Actions "Dependencies lock file is not found" (setup-node cache)
setup-node's built-in cache keys on a lockfile. If no package-lock.json, yarn.lock, or pnpm-lock.yaml is found at the expected path, it cannot compute the cache key and fails.
What this error means
The setup-node step fails with "Dependencies lock file is not found" listing the patterns it searched, usually when the lockfile lives in a subdirectory or was not committed.
Error: Dependencies lock file is not found in /home/runner/work/repo/repo. Supported file patterns: package-lock.json, npm-shrinkwrap.json, yarn.lockDiagnose 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.
- 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 }}"Common causes
Lockfile in a subdirectory
The project lives in a subfolder (monorepo package), but the cache search runs from the repo root and finds no lockfile there.
Lockfile not committed
package-lock.json / yarn.lock is gitignored or never committed, so checkout produces a tree with no lockfile to key on.
How to fix it
Point the cache at the real lockfile
- Set cache-dependency-path to the lockfile location.
- Commit the lockfile so it is present after checkout.
- For monorepos, pass the subdirectory path or a glob.
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: packages/app/package-lock.jsonCache 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.
How to prevent it
- Commit lockfiles and keep them out of .gitignore.
- Set cache-dependency-path for non-root projects.
- Run checkout before setup-node so the lockfile exists.