# GitHub Actions Dependencies lock file is not found in setup-node

> GitHub Actions Dependencies lock file is not found means setup-node read the repository root and gave up. Point cache-dependency-path at the file.

Source: https://latchkey.dev/learn/github-actions/gha-setup-node-lock-file-not-found  
Updated: 2026-09-20

A GitHub Actions Dependencies lock file is not found error is `actions/setup-node` refusing to guess: with `cache` set and no `cache-dependency-path`, it reads the workspace root one level deep and looks for one of three exact filenames. The list of filenames it prints tells you which package manager it thought you were using, and that is often the real mistake.

## What this error means

The job fails inside Set up Node.js, before a single dependency is installed, and the step has already printed the Node version it resolved. The failure line names an absolute path, which is the checkout directory, and then a comma-separated list of filenames with no spaces between them. Nothing in the run is wrong except that the action could not find a file to hash for a cache key. If you have just moved the project into a monorepo, or just added `cache: npm` to a step that did not have it, this is the failure you get on the next push.

```Actions log, quoted from JustAlexeyDev/EvaOS#19
Error: Dependencies lock file is not found in /home/runner/work/EvaOS/EvaOS. Supported file patterns: package-lock.json,npm-shrinkwrap.json,yarn.lock
```

## Common causes

### The lockfile is real but is not at the top of the checkout

The common one by a wide margin. A monorepo, a repository whose application lives under `app/`, or a workspace root holding only a `package.json` all fail this way. The action never descends, so a lockfile two directories down is invisible to it. The path in the message is the checkout root, and the file you are thinking of is not in it.

### setup-node runs before actions/checkout

If the checkout has not happened, `GITHUB_WORKSPACE` exists and is empty, so the listing is empty and the search fails at once. Every example in the action's own documentation puts `actions/checkout` first. This is easy to create by accident when steps are reordered to speed a job up, because setup-node is fast and looks like it should go first.

### The lockfile is not committed

A lockfile in `.gitignore` is not in the checkout, so it is not in the listing either. This is commoner than it sounds in repositories that were once libraries, because ignoring the lockfile is reasonable advice for a published package and the opposite of what a caching CI job needs. If `git ls-files` does not print it, the runner will not see it.

### The cache value names a package manager you are not using

The three lists are not interchangeable, and one gap catches people repeatedly: `cache: npm` accepts a `yarn.lock`, but nothing except `cache: pnpm` accepts a `pnpm-lock.yaml`. A pnpm repository with `cache: npm` copied from a template fails every time, and the printed list is the tell, because it will not mention pnpm at all.

## How to fix it

### Read the filename list before you touch the path

1. Take the comma-separated list from the message and compare it to the lockfile you actually have.
2. If your lockfile is not in that list, the `cache` value names the wrong package manager, and the path is not the problem.
3. If it is in the list, compare the path in the message to where the file really is.
4. Confirm the file is committed with `git ls-files` before assuming the action is at fault.

### Point cache-dependency-path at the file you have

The fix for every layout where the lockfile is not at the root, and the illustrative workflow above with one input added. The value is relative to the workspace, so it starts at the repository root regardless of any `working-directory` on a later step.

```.github/workflows/ci.yml, corrected (illustrative)
- uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm
          cache-dependency-path: packages/app/package-lock.json
      - run: npm ci
        working-directory: packages/app
```

### Use a glob or a list when there is more than one lockfile

The input takes a wildcard or a multiline list, and the advanced usage guide documents both. A glob keys the cache on every lockfile in the tree, so any dependency change invalidates it: right for a workspace installed from the root, wrong for independent packages that should each keep their own cache.

```.github/workflows/ci.yml (illustrative)
- uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: pnpm
          cache-dependency-path: |
            packages/app/pnpm-lock.yaml
            packages/api/pnpm-lock.yaml
```

### If you do not want the cache, turn it off rather than working around it

Creating an empty lockfile at the root to satisfy the search is a fix that will produce a cache key nobody wants and a restore that never helps. If the job genuinely has nothing worth caching, drop the `cache` input, or set `package-manager-cache` to false, which the action has carried since version 5 and which disables the built-in caching without disabling the action.

```.github/workflows/ci.yml (illustrative)
- uses: actions/setup-node@v7
        with:
          node-version: 24
          package-manager-cache: false
```

## How to prevent it

- Set `cache-dependency-path` on every repository whose lockfile is not at the root, even before it breaks.
- Keep `actions/checkout` as the first step in any job that reads the working tree.
- Commit lockfiles in anything that is deployed or tested, whatever the library advice says.
- Match the `cache` value to the lockfile you have, not to the package manager you used last year.

## A minimal workflow that produces it

This file is written for this page and has never been run. It is the smallest shape that produces the error: an application in `packages/app`, a `cache` input with nothing telling the action where to look, and a lockfile that is committed one directory below where the action searches. The checkout is present and correct, which is the point.

```.github/workflows/ci.yml (illustrative)
name: ci
on:
  push:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm
      - run: npm ci
        working-directory: packages/app
```

## The search is one directory deep and matches exact names

The function that raises this is `findLockFile` in the action source: twelve lines and six statements, of which the two below are the search and its guard. It reads the workspace directory, takes the package manager's list of lockfile names, and returns the first name in that listing. There is no recursion and no glob: the match is an exact string comparison against the entries at the top of the checkout.

That is why the message prints a path and a list. The path is `GITHUB_WORKSPACE`, so it says where the action looked, and the list is its own record of what it wanted. Which list you get depends on the value of `cache`, and the three do not overlap the way people assume.

```actions/setup-node, src/cache-restore.ts
const lockFile = lockFiles.find(item => rootContent.includes(item));
if (!lockFile) {
  throw new Error(
    `Dependencies lock file is not found in ${workspace}. Supported file patterns: ${lockFiles.toString()}`
  );
}
```

| `cache` value | Filenames it looks for, in order | Where it looks |
| --- | --- | --- |
| `npm` | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | The top level of the checkout, only |
| `yarn` | `yarn.lock` | The top level of the checkout, only |
| `pnpm` | `pnpm-lock.yaml` | The top level of the checkout, only |

## Setting cache-dependency-path changes which error you get

The branch above runs only when `cache-dependency-path` is empty. Set it, and the action skips `findLockFile` and hands your value straight to `hashFiles`, which is a glob. A glob that matches nothing has no filename list to print, so it raises different text instead: `Some specified paths were not resolved`, followed by an explanation that it cannot cache dependencies.

The two messages are a diagnostic, not a nuisance. The one with the filename list means the action was guessing and guessed an empty directory. The other means you said exactly where to look and it found nothing there, which is usually a typo, a path relative to the wrong root, or a lockfile in `.gitignore`.

The README states the default plainly: the action "defaults to search for the dependency file (`package-lock.json`, `npm-shrinkwrap.json` or `yarn.lock`) in the repository root", and points at `cache-dependency-path` "for cases when multiple dependency files are used, or they are located in different subdirectories". A monorepo is always the second case.

| What you set | What the action does | What a miss says |
| --- | --- | --- |
| `cache` only | Reads the checkout root for known filenames | Dependencies lock file is not found, with the list |
| `cache` and `cache-dependency-path` | Globs your pattern and hashes the matches | Some specified paths were not resolved |
| Neither | No cache, no lockfile lookup, no failure | Nothing, and every run downloads again |

> A cache that is found and keyed but never restores is a different problem: see [GitHub Actions cache not restored](/learn/speed/github-actions-cache-not-restored).

## Why there is no recorded run on this page

The failure happens inside an action before any shell runs, so there is no runner state involved, nothing transient to retry, and nothing a managed runner could repair: the file is either at the path the action reads or it is not, on every attempt. So this page carries an illustrative workflow and a quoted source line rather than a reproduction, and the log above is taken verbatim from a public issue.

## FAQ

### How do I fix Dependencies lock file is not found in a monorepo?

Set `cache-dependency-path` on the setup-node step to the lockfile path, relative to the repository root. The default search reads only the top level of the checkout, so a lockfile in `packages/app` is invisible to it whatever the later steps set `working-directory` to. A wildcard matching every lockfile in the tree works too, at the cost of a key that changes whenever any package does.

### Which lock files does setup-node look for?

It depends on the `cache` value, and the message prints the list it used. With `cache: npm` it looks for `package-lock.json`, then `npm-shrinkwrap.json`, then `yarn.lock`. With `cache: yarn` it looks only for `yarn.lock`, and with `cache: pnpm` only for `pnpm-lock.yaml`. Nothing else is recognized, and no value falls back to another manager's list.

### Why does setup-node say some specified paths were not resolved instead?

Because you set `cache-dependency-path`, which replaces the built-in search with a glob, so there is no filename list left to print. Treat it as the more specific of the two errors: the action looked exactly where you told it to and found nothing, so check the pattern and check that the file is committed.

### Do I need to commit package-lock.json for GitHub Actions caching?

Yes, if you want setup-node to cache anything. The cache key is a hash of the lockfile, so a lockfile that is in `.gitignore` is not in the checkout and there is nothing to hash. It is also what makes `npm ci` reproducible, so the two requirements point the same way.

## References

- [actions/setup-node README: caching packages data and cache-dependency-path](https://github.com/actions/setup-node#caching-global-packages-data)
- [actions/setup-node advanced usage: wildcards and lists of lockfile paths](https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-data)
- [An issue whose title is the error line, path and filename list included](https://github.com/JustAlexeyDev/EvaOS/issues/19)
- [GitHub Actions: dependency caching reference, including the setup-* actions](https://docs.github.com/en/actions/reference/workflows-and-actions/dependency-caching)

---

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
