No pnpm version is specified in pnpm/action-setup
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.
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"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. |
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
- Look at the job in the run, not at the repository, and find whether
actions/checkoutran before the pnpm step. - If it did not, move it above and re-run; nothing else needs to change.
- 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.
{
"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.
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
with:
package_json_file: packages/app/package.jsonA 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.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: pnpm/action-setup@v6
- uses: actions/checkout@v7
- run: pnpm installWhy 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.
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:
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_VERSIONWhich 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.
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
with:
version: 10
- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpmWhy 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.
How to prevent it
- Put
actions/checkoutfirst in every job that sets up a package manager from the manifest. - Keep the pnpm version in one place, and make that place
packageManagerif developers run pnpm locally. - Never set both
versionandpackageManagerto different values, since the action refuses rather than choosing. - Order
actions/setup-nodewithcache: pnpmafter the pnpm step, so the cache path resolves against the version you asked for.
Frequently asked questions
Why does pnpm/action-setup say no version when package.json has packageManager?
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?
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?
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?
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.Related guides
References
- pnpm/action-setup: src/install-pnpm/run.ts, readTargetVersion and its three throws
- pnpm/action-setup: README, when the version input is optional and what it accepts
- pnpm/action-setup: action.yml, the package_json_file input and its default
- Node.js: the packageManager field, which the action reads
- Node.js documentation
- npm CLI documentation
- GitHub Actions documentation