Skip to content
loke.dev
Packages moving along a bright bypass around a broken conveyor belt

Fix pnpm “Cannot Use 'in' Operator” in GitHub Actions

Fix pnpm's integrity undefined crash in GitHub Actions by replacing broken 11.12.0, pinning one version, and updating the setup step safely.

Published Updated 5 min read

The short fix

If GitHub Actions fails before install withCannot use 'in' operator to search for 'integrity' in undefined, check the pnpm version before changing dependencies. pnpm 11.12.0 triggered this crash while its setup process read pnpm's own environment lockfile. It's not evidence that your repository'spnpm-lock.yamlis corrupt.

Move the workflow off 11.12.0. As of August 4, 2026, the npm registry lists pnpm 11.20.0 as the current stable release. Pin that exact version, rerun the job, and review the normal project lockfile only if the install step later changes it.

{
  "packageManager": "pnpm@11.20.0"
}

Thepnpm core issueidentifies 11.12.0 and the failing global environment-lockfile path. A separatepnpm/action-setup reportreproduces the same error on a GitHub runner while switching from pnpm 11.7.0 to 11.12.0. These are two independent reports of the same failure.

Recognize this failure before changing your app

The useful clues appear before your package install starts:

  • The setup step says it's switching or self-installing pnpm.
  • The selected version is pnpm 11.12.0, often from packageManager, devEngines.packageManager, or a latest-style action input.
  • The stack includes createFullPkgId, lockfileToDepGraph, or installPnpmToGlobalDir.
  • The final action message says the self-installer exited with code 1.

If the failure starts insidepnpm installand names a package from your project, this article may not match. Save the first error, the pnpm version, and the workflow step instead of diagnosing from the wordintegrityalone.

Why deleting the project lockfile is the wrong first move

The pnpm report traces this crash to the package manager's global environment lockfile. Peer-variant snapshots could be read without the matching package metadata, leaving the later integrity lookup with an undefined value. The failing file is part of pnpm's own version-management environment, not the lockfile committed with your application.

Don't delete the repository'spnpm-lock.yamlto repair this setup error. That would rewrite application dependency resolution while leaving the real version-selection problem untouched.

For a local machine already stuck on the broken release, the core issue lists platform-specific locations for the global environment lockfile and says removing that file lets self-update continue. Back it up before removal and verify the exact path on your machine. A GitHub-hosted runner is disposable, so changing the committed pnpm pin and starting a new job is usually cleaner.

Pin one known-good version for local work and CI

Put the exact pnpm version inpackage.jsonso the repository, developers, and setup action share one source of truth. Avoidlatestin a release workflow. A new package-manager release should arrive as a reviewed dependency change, not as an unannounced change between two identical commits.

{
  "name": "web-app",
  "private": true,
  "packageManager": "pnpm@11.20.0",
  "scripts": {
    "check": "pnpm lint && pnpm test && pnpm build"
  }
}

The JSON above is a minimal example and was syntax-checked. Keep the scripts and fields your project already owns. If the repository usesdevEngines.packageManagerinstead, update that existing declaration rather than adding a second conflicting pin.

The merged pnpm guard tested 11.11.0 and 11.13.1 as working targets, while refusing known-broken releases. It also calls out 11.13.0 as unsafe for@pnpm/exeeven though the JavaScript wrapper could run. That's why this guide doesn't recommend moving from 11.12.0 to 11.13.0. Seepnpm pull request #13082for the test matrix and refusal behavior.

Update the GitHub Actions setup step

The currentpnpm/action-setup READMEsays pnpm 11 and newer should use the successor action,pnpm/setup. It installs pnpm as a standalone executable and can install the JavaScript runtime in the same step.

This workflow follows the documented input names. It's illustrative because your Node version, caching policy, and install command belong to your project:

steps:
  - uses: actions/checkout@v6

  - uses: pnpm/setup@v1
    with:
      runtime: node@24
      cache: true
      install: false

  - run: pnpm install --frozen-lockfile
  - run: pnpm run check

The action can read pnpm 11 frompackageManager, so the workflow doesn't need a second version value.install: falsekeeps the explicit frozen install step. without it,pnpm/setupinstalls automatically when it finds a package manifest.

If you must stay onpnpm/action-setup@v6for a short migration window, omit its version input and let the action read the exactpackageManagervalue. Don't keepversion: latestnext to an exact repository pin because the action input takes precedence.

Recover a local pnpm that can't update itself

A local recovery should preserve evidence and avoid broad deletion:

  1. Record pnpm --version and the full error.
  2. Inspect packageManager and devEngines.packageManager in the nearest package.json.
  3. Replace a known-broken pin with a reviewed current version.
  4. Try pnpm self-update latest if the installed binary can still run that command.
  5. If self-update still hits the same environment-lockfile error, back up only the global pnpm lockfile at the platform path documented in the issue, then retry.
  6. Run pnpm --version again, followed by the project's frozen install and normal checks.

pnpm'sself-update documentationdescribes the update command. Itsinstallation guidelists supported installation paths if the current binary can't recover itself. Use the method your team already manages instead of layering multiple global installations.

Check the fix without hiding another failure

A green setup step is only the first checkpoint. Verify the workflow in order:

  • The setup log reports the exact pnpm version you pinned.
  • pnpm install --frozen-lockfile succeeds without rewriting the project lockfile.
  • The cache key uses the intended pnpm-lock.yaml.
  • Lint, tests, and the production build run after setup.
  • A fresh pull request runner produces the same result.

Don't add--force, remove the frozen-lockfile check, or commit a regenerated lockfile just to get past a package-manager bootstrap crash. Those changes widen the dependency diff without addressing the broken pnpm release.

Keep the pin reviewable

An exact package-manager pin is useful only if someone updates it deliberately. Let Renovate or Dependabot propose pnpm changes, keep setup and install in separate log sections, and test the package-manager update on a fresh runner before merging.

If the upgrade also moves an older pnpm 11 project configuration, review loke.dev'spnpm 11 configuration migration guide. The self-installer crash and the workspace-configuration move are separate problems, so solve them in separate diffs.

Sources

Primary technical sources:pnpm issue #12959.pnpm/action-setup issue #276.pnpm pull request #13082. the currentpnpm setup-action README.pnpm self-update docs. and thepnpm installation guide.