4 Pitfalls I Hit Upgrading pnpm v10 to v11 — A Summary of Fixes for Docker and CI Environments

4 Pitfalls I Hit Upgrading pnpm v10 to v11 — A Summary of Fixes for Docker and CI Environments

Based on my real experience of breaking Docker and CI environments when upgrading pnpm from v10 to v11, I will explain 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. The local environment went relatively smoothly, but the Docker build and CI pipeline broke spectacularly.

In this article, I'll share the pitfalls I actually encountered and how to deal with them in a "hands-on" format. Honestly, pnpm v11 has quite a few breaking changes, and even after reading the official documentation, there are several traps that are 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) were executed with a warning, but in v11 they result in an error 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. They need to be migrated to pnpm-workspace.yaml.

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

3. Environment variable prefix has changed

npm_config_* → changed to pnpm_config_*. Requires fixes in CI environments or Dockerfiles using npm_config_*.

4. Node.js 22 or higher is 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 occur for packages requiring native builds such as sharp (image processing) and unrs-resolver (for ESLint).

Solution: Add allowBuilds to pnpm-workspace.yaml.

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

It was also needed 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 error messages from pnpm install. Just add the package names shown in the errors to allowBuilds and you're done.

onlyBuiltDependencies / neverBuiltDependencies / ignoredBuiltDependencies from v10 and earlier are deprecated, so if you're already using these, you'll need to rewrite them as 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 isn't loaded, postinstall scripts get blocked, and the Docker build fails.

Pitfall 3: ENV CI=true is required inside Docker

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

The cause was that when pnpm v11 detects an unauthorized postinstall script, it interactively prompts whether to allow it. Since there's no TTY during a Docker build, this prompt either hangs or errors out.

Solution: Setting ENV CI=true puts pnpm into non-interactive mode, so it behaves according to 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 of ENV CI=true, but without it, the Docker build silently stops, which made it time-consuming to identify the cause.

Pitfall 4: verifyDepsBeforeRun breaks 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's an inconsistency.

While this seems convenient, in VPN-connected or restricted network environments, registry fetches fail and produce errors like:

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

Even if node_modules is fully populated, network access occurs during the automatic check → automatic install process, meaning even pnpm run cannot be executed in offline environments or behind a firewall.

Solution: 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 works, 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 entirely, setting it to warn will perform the check but only show a warning without automatically installing:

verifyDepsBeforeRun: warn

CI (GitHub Actions) Fixes

In GitHub Actions, the version specification for pnpm/action-setup also needed to be updated.

# 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 those needed inside Docker were required. However, if pnpm-workspace.yaml is not properly committed to the repository, the same ERR_PNPM_IGNORED_BUILDS error will appear in CI as well.

Honest Impressions

Upgrading to pnpm v11 was, frankly speaking, a pain.

The good:

  • Explicit 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 within the last 24 hours) is similarly a good decision
  • Having configuration centralized in pnpm-workspace.yaml is clearer in the long run

The painful:

  • The "warning → error" change is the most impactful breaking change for users, and it's especially likely to be noticed for the first time in non-interactive environments like CI/Docker
  • The need to COPY pnpm-workspace.yaml in Dockerfiles should have been written more prominently in the official documentation's Docker guide
  • The requirement for ENV CI=true was not documented anywhere and could only be discovered through trial and error
  • The verifyDepsBeforeRun=install default causes pnpm run to suddenly break in offline or VPN environments. Moreover, since configuration via .npmrc is ignored, it takes time to identify the cause
  • There are too many breaking changes, making it difficult to grasp everything at once even after reading the official migration guide

Ultimately, pnpm v11 represents a major shift toward a security-first design philosophy. Changes like the default denial for allowBuilds, minimumReleaseAge, and blockExoticSubdeps all lean toward the "safe side." I think the direction is right, but the migration cost is considerable.

Upgrade Steps Summary

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

Share this article