4 Pitfalls I Hit When Upgrading from pnpm v10 to v11 — Solutions for Docker and CI Environments

4 Pitfalls I Hit When Upgrading from pnpm v10 to v11 — Solutions for Docker and CI Environments

Based on real experience of breaking Docker and CI environments when upgrading pnpm from v10 to v11, this article explains three solutions: configuring allowBuilds, adding pnpm-workspace.yaml to the Dockerfile, and setting ENV CI=true.
2026.05.29

This page has been translated by machine translation. View original

Introduction

pnpm v11 was released, and I upgraded my project's package manager from v10. Things went relatively smoothly in my local environment, but the Docker build and CI pipeline broke spectacularly.

In this article, I'll share the pitfalls I actually ran into and how I dealt with them, in a "here's what I tried" format. To be honest, pnpm v11 has quite a few breaking changes, and even after reading the official documentation, there were several traps that were easy to miss.

Prerequisites & Environment

  • pnpm: v10.32.1 → v11 (latest)
  • Node.js: 24 (LTS)
  • Framework: Next.js 16
  • Docker: node:24-slim base image
  • CI: GitHub Actions

Major Breaking Changes in pnpm v11

Here's a summary of the key changes you should know before upgrading.

1. postinstall scripts are blocked by default

This was the biggest trap. Up through v10, postinstall scripts (such as building native modules) ran with a warning, but in v11 they error out unless explicitly permitted.

 ERR_PNPM_IGNORED_BUILDS  The following dependencies have build scripts that are not executed: sharp, unrs-resolver

2. The location of configuration files has changed

pnpm-specific settings written in .npmrc (such as hoist-pattern, node-linker, save-exact, etc.) are not read in v11. You need to migrate them to pnpm-workspace.yaml.

Setting type v10 v11
Registry & authentication .npmrc .npmrc (unchanged)
pnpm-specific settings .npmrc pnpm-workspace.yaml
package.json#pnpm Read Ignored

3. The environment variable prefix has changed

npm_config_* → changed to pnpm_config_*. Requires fixes if you're using npm_config_* in CI environments or Dockerfiles.

4. Node.js 22 or higher is now required

Support for Node.js 18–21 has been dropped.

4 Pitfalls I Actually Fell Into

Pitfall 1: Allowing postinstall scripts with allowBuilds

When running pnpm install, errors appear for packages that require native builds, such as sharp (image processing) and unrs-resolver (for ESLint).

Fix: Add allowBuilds to pnpm-workspace.yaml.

# frontend/pnpm-workspace.yaml
allowBuilds:
  sharp: true
  unrs-resolver: true

I also needed it at the project root for other packages:

# pnpm-workspace.yaml (root)
allowBuilds:
  cpu-features: true
  ssh2: true

Key point: You can tell which packages are affected by looking at the pnpm install error messages. Just add the package names shown in the errors to allowBuilds and you're good.

onlyBuiltDependencies / neverBuiltDependencies / ignoredBuiltDependencies from v10 and earlier have been removed, so if you're already using any of these, you'll need to rewrite them using allowBuilds.

Pitfall 2: Forgetting to COPY pnpm-workspace.yaml in the Dockerfile

pnpm-workspace.yaml has become a required configuration file in v11. However, the existing Dockerfile only COPYed package.json and pnpm-lock.yaml.

Before (broken):

COPY frontend/package.json frontend/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

After (working):

COPY frontend/package.json frontend/pnpm-lock.yaml frontend/pnpm-workspace.yaml ./
RUN pnpm install --frozen-lockfile

Without pnpm-workspace.yaml, the allowBuilds configuration won't be loaded, postinstall scripts will be blocked, and the Docker build will fail.

Pitfall 3: ENV CI=true is required inside Docker

Even after fixing the above two issues, pnpm install inside Docker still failed in some cases.

The cause was that pnpm v11 now interactively prompts you to decide whether to allow postinstall scripts when it detects ones that aren't permitted. Since there's no TTY during a Docker build, this prompt either hangs or errors out.

Fix: Setting ENV CI=true puts pnpm into non-interactive mode, causing it to follow the allowBuilds configuration without showing any prompts.

FROM node:24-slim
ENV CI=true
RUN corepack enable && corepack prepare pnpm@latest --activate

WORKDIR /app

COPY frontend/package.json frontend/pnpm-lock.yaml frontend/pnpm-workspace.yaml ./
RUN pnpm install --frozen-lockfile

It's just one line — ENV CI=true — but without it, the Docker build silently hangs, which made it time-consuming to identify the cause.

Pitfall 4: verifyDepsBeforeRun breaking pnpm run in offline environments

In pnpm v11, verifyDepsBeforeRun is set to install by default. This is a feature that checks the state of dependencies every time pnpm run is executed, and automatically runs pnpm install if there are any inconsistencies.

It seems convenient at first glance, but when using a VPN or in restricted network environments, fetches to the registry fail with errors like the following:

TypeError: fetch failed
    at Object.processResponse (...)
[ERROR] Command failed with exit code 1: ... pnpm.mjs install

Even when node_modules is fully intact, the automatic check → automatic install process triggers network access, resulting in a situation where pnpm run can't even execute in offline environments or behind a firewall.

Fix: Disable verifyDepsBeforeRun in pnpm-workspace.yaml.

verifyDepsBeforeRun: false

allowBuilds:
  cpu-features: true
  ssh2: true

Note: Writing verify-deps-before-run=false in .npmrc does not work. In pnpm v11, this setting is only read from pnpm-workspace.yaml. The environment variable PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false does work, but setting it inside a script definition in pnpm run is too late (the check runs before pnpm executes the script).

If you don't want to disable it completely, setting it to warn will perform the check but only show a warning without auto-installing:

verifyDepsBeforeRun: warn

CI (GitHub Actions) Fixes

In GitHub Actions, I also needed to update the version specified for pnpm/action-setup.

# Before
- uses: pnpm/action-setup@v4
  with:
    version: 10

# After
- uses: pnpm/action-setup@v4
  with:
    version: latest

Since CI=true is set by default in GitHub Actions environments, no additional workarounds like the ones needed inside Docker were required. However, if pnpm-workspace.yaml isn't properly committed to the repository, you'll get the same ERR_PNPM_IGNORED_BUILDS error in CI as well.

Honest Thoughts

To be frank, upgrading to pnpm v11 was a pain.

The good:

  • Explicitly requiring permission for postinstall scripts via allowBuilds is the right direction from a security standpoint, as a defense against supply chain attacks
  • The default enabling of minimumReleaseAge (not resolving packages published less than 24 hours ago) is similarly a good decision
  • Having settings consolidated in pnpm-workspace.yaml will be clearer in the long run

The painful parts:

  • The "warning → error" change is the most impactful breaking change for users, and you only notice it in non-interactive environments like CI/Docker
  • The need to COPY pnpm-workspace.yaml into the Dockerfile should have been written more prominently in the official Docker guide
  • The fact that ENV CI=true is required was not documented anywhere, and I had no choice but to discover it through trial and error
  • The default of verifyDepsBeforeRun=install causes pnpm run to suddenly break in offline or VPN environments. On top of that, since settings in .npmrc are ignored, it takes time to identify the cause
  • There are so many breaking changes that it's hard to grasp them all at once even after reading the official migration guide

All in all, pnpm v11 represents a major shift toward a security-first design philosophy. The default denial in allowBuilds, minimumReleaseAge, blockExoticSubdeps — all of these are changes that "err on the side of safety." I think the direction is right, but the migration cost is not trivial.

Summary of Upgrade Steps

  1. Run pnpx codemod run pnpm-v10-to-v11 to perform mechanical configuration migration
  2. Run pnpm install and check the package names that appear in ERR_PNPM_IGNORED_BUILDS errors
  3. Add allowBuilds to pnpm-workspace.yaml
  4. Add the COPY of pnpm-workspace.yaml to the Dockerfile
  5. Add ENV CI=true to the Dockerfile
  6. Update the pnpm version in your CI configuration (GitHub Actions, etc.)
  7. Migrate pnpm-specific settings from .npmrc to pnpm-workspace.yaml
  8. Set verifyDepsBeforeRun to false or warn for offline/restricted network environments
  9. Regenerate the lockfile (automatically updated by pnpm install)

Share this article