# No pnpm version is specified in pnpm/action-setup

> No pnpm version is specified means the action looked in three places and found nothing. Here is the order it checks, and the two errors near it.

Source: https://latchkey.dev/learn/github-actions/pnpm-action-setup-no-version-specified  
Updated: 2026-09-20

No pnpm version is specified is thrown after pnpm/action-setup has looked in three places and found a version in none of them. It is not a network failure and not a registry problem: the action never reached the point of installing anything, because it did not know what to install.

## What this error means

The step fails in seconds, before any download, with a five-line message: a headline, one line of instruction, and a bullet for each of the three places it looked. Nothing has been installed, so `pnpm` is not on the path and every later step that uses it fails too, usually with a command-not-found that sends people to the wrong page. The message is fixed text with no interpolation, so it reads identically in every repository. Two of its three bullets mention `package.json`, which is the hint: the action almost always failed because it could not read that file, not because the file lacks a field.

```pnpm/action-setup, src/install-pnpm/run.ts
No pnpm version is specified.
Please specify it by one of the following ways:
  - in the GitHub Action config with the key "version"
  - in the package.json with the key "packageManager"
  - in the package.json with the key "devEngines.packageManager"
```

## Common causes

### actions/checkout has not run yet

The common one, and the one the message actively disguises. The action reads `package.json` from the workspace, the read fails because nothing has been checked out, and that failure is swallowed on purpose so a repository with no manifest still works. What is left is a lookup with nothing in it.

### The repository genuinely declares no pnpm version

No `version` input, no `packageManager`, no `devEngines.packageManager`. The action does not guess, which is the right call: a silently chosen version is how a lockfile gets rewritten by a major nobody selected.

### The manifest is not at the workspace root

A monorepo where the root has no `package.json`, or one where it sits under a subdirectory. The action looks at the path in `package_json_file`, which defaults to `package.json` and is documented as relative to the repository root, so a manifest elsewhere is simply not seen.

### The field exists but is not in a form the action accepts

A `packageManager` value that names something other than pnpm is ignored, because the action checks that the string starts with the pnpm prefix before it takes anything from it. A `devEngines.packageManager` entry whose name is not pnpm is skipped for the same reason.

## How to fix it

### Check the step order before you edit package.json

1. Look at the job in the run, not at the repository, and find whether `actions/checkout` ran before the pnpm step.
2. If it did not, move it above and re-run; nothing else needs to change.
3. If it did, open the manifest the action would have read and confirm it declares a version in one of the two fields.

### Pin the version in the manifest

The better default for a repository with developers on it, because their local tooling reads the same field. Set it once and the workflow needs no version at all.

```package.json (illustrative)
{
  "name": "example",
  "packageManager": "pnpm@10.9.8"
}
```

### Or pin it on the step, and then only there

Use the `version` input when there is no manifest to carry the value. Do not set both unless they agree, since a disagreement is the `Multiple versions of pnpm specified:` error rather than a precedence rule.

### Point the action at the manifest when it is not at the root

Give `package_json_file` a path relative to the workspace root. This is the monorepo answer, and it keeps the version in one file rather than repeating it across every workflow that needs pnpm.

```.github/workflows/ci.yml (illustrative)
- uses: actions/checkout@v7
      - uses: pnpm/action-setup@v6
        with:
          package_json_file: packages/app/package.json
```

## How to prevent it

- Put `actions/checkout` first in every job that sets up a package manager from the manifest.
- Keep the pnpm version in one place, and make that place `packageManager` if developers run pnpm locally.
- Never set both `version` and `packageManager` to different values, since the action refuses rather than choosing.
- Order `actions/setup-node` with `cache: pnpm` after the pnpm step, so the cache path resolves against the version you asked for.

## The order the action resolves a version in

All of this happens in one function, `readTargetVersion` in `src/install-pnpm/run.ts`. It reads the manifest first if it can, then works down a list, and the message you get depends entirely on where it stopped. Reading the order explains why adding `packageManager` sometimes fixes nothing and why adding `version` sometimes breaks a working workflow.

| Step | What the action checks | Outcome |
| --- | --- | --- |
| 1 | The `version` input, when `packageManager` names a different version | Throws `Multiple versions of pnpm specified:` |
| 2 | The `version` input, otherwise | Uses it and stops looking |
| 3 | `devEngines.packageManager` with a name of `pnpm` | Uses its version |
| 4 | `packageManager`, with any integrity hash stripped | Uses that version |
| 5 | No `GITHUB_WORKSPACE` in the environment | Throws `No workspace is found.` |
| 6 | Nothing left | Throws `No pnpm version is specified.` |

> Step 3 before step 4 is deliberate: `devEngines.packageManager` takes priority over `packageManager`, so a repository that carries both is installing whichever the first one names.

## A workflow that produces it

This file is written for this page and has never been run. It is the shape that produces the error most often, and the defect is the missing checkout rather than anything about pnpm. Without it the workspace is empty, the read of `package.json` fails with a not-found that the action deliberately swallows, and the lookup falls all the way through to step six.

```.github/workflows/ci.yml (illustrative)
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: pnpm/action-setup@v6
      - uses: actions/checkout@v7
      - run: pnpm install
```

## Why a missing checkout does not say so

There is a message for a missing workspace, and it would be the useful one here, but it almost never fires on GitHub-hosted runners. The action only throws `No workspace is found.` when the `GITHUB_WORKSPACE` environment variable is absent entirely, and the runner always sets it, even when the directory it points at is empty. A missing or late `actions/checkout` therefore lands on step six instead of step five.

That is worth knowing, because the message it does throw sends you to `package.json` to add a field that is already there in the repository you are looking at. The file is simply not on disk yet at the moment the action reads it.

```pnpm/action-setup, src/install-pnpm/run.ts
No workspace is found.
If you've intended to let pnpm/action-setup read preferred pnpm version from the "packageManager" field in the package.json file,
please run the actions/checkout before pnpm/action-setup.
Otherwise, please specify the pnpm version in the action configuration.
```

## The opposite error, which looks like this one

If both the `version` input and `packageManager` are set and they disagree, the action refuses rather than choosing, and the message begins with a header that is easy to mistake for the one on this page. It names both values and both sources, so it is unambiguous once you read past the first line:

```pnpm/action-setup, src/install-pnpm/run.ts (values illustrative)
Multiple versions of pnpm specified:
  - version 9 in the GitHub Action config with the key "version"
  - version pnpm@10.9.8 in the package.json with the key "packageManager"
Remove one of these versions to avoid version mismatch errors like ERR_PNPM_BAD_PM_VERSION
```

> The two lines in the middle interpolate whatever your workflow and manifest actually say, so the versions above are placeholders and the rest of the text is fixed.

## Which field to reach for

The README is direct about when the input is optional: `version` is "**Optional** when there is a [`packageManager` or `devEngines.packageManager` field in the `package.json`]", and "otherwise, this field is **required**". It accepts more than an exact pin, listing "an exact version (such as `10.9.8`), or a version range (such as `10`, `10.x.x`, `10.9.x`, `^10.9.8`, `*`, etc.), or `latest`".

Prefer the manifest field when your developers already have one, because it is the same value their local tooling reads and there is then only one number to bump. The action strips an integrity suffix for you, so a `packageManager` of the form `pnpm@10.9.8+sha512...` resolves to the version before the plus. If the repository has no `package.json` at the root, or the one it has is somewhere else, the `package_json_file` input takes a path relative to the workspace root.

```.github/workflows/ci.yml (illustrative)
- uses: actions/checkout@v7
      - uses: pnpm/action-setup@v6
        with:
          version: 10
      - uses: actions/setup-node@v7
        with:
          node-version: 22
          cache: pnpm
```

## Why there is no recorded run on this page

The error is thrown by a pure function reading two inputs and a file, before the action spawns a process or touches the network. There is nothing for a runner to influence and nothing transient to catch, so a recorded run would be a screenshot of a string this page already quotes from the line that throws it. The workflows above are illustrative, and the message text is quoted from the action's source at the current major.

## FAQ

### Why does pnpm/action-setup say no version when package.json has packageManager?

Because it read the workspace before `actions/checkout` put the file there. The read fails with a not-found that the action swallows deliberately, so the lookup ends with nothing and throws this message. Move the checkout above the pnpm step and the same manifest resolves.

### Does devEngines.packageManager override packageManager for pnpm?

Yes. The action checks `devEngines.packageManager` before `packageManager`, and takes its version when the name is `pnpm`. A repository carrying both installs whatever `devEngines` names, so if the two have drifted apart the second one is doing nothing.

### What does "Multiple versions of pnpm specified" mean?

That the `version` input and the `packageManager` field both exist and name different versions. The action refuses to pick and tells you to remove one, naming the mismatch error it is trying to save you from. It is the opposite condition to this page, not a variant of it.

### Can I give pnpm/action-setup a version range instead of an exact version?

Yes. Its README lists an exact version such as `10.9.8`, a range such as `10`, `10.x.x`, `10.9.x`, `^10.9.8` or `*`, and `latest`. A `packageManager` field is exact by specification, so a range has to go in the `version` input, and then the field must not disagree with it.

## References

- [pnpm/action-setup: src/install-pnpm/run.ts, readTargetVersion and its three throws](https://github.com/pnpm/action-setup/blob/master/src/install-pnpm/run.ts)
- [pnpm/action-setup: README, when the version input is optional and what it accepts](https://github.com/pnpm/action-setup#version)
- [pnpm/action-setup: action.yml, the package_json_file input and its default](https://github.com/pnpm/action-setup/blob/master/action.yml)
- [Node.js: the packageManager field, which the action reads](https://nodejs.org/api/corepack.html)

---

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
