parcel-bundler/parcel · error · Error

pnpm failed to install modules

Error message

pnpm failed to install modules

What it means

Thrown by the Pnpm package installer when the pnpm install subprocess fails. Unlike the Npm and Yarn wrappers, this error discards the caught exception's message entirely — it throws a bare 'pnpm failed to install modules' string with no error details. This makes debugging harder since the original error context (stderr, exit code, exception message) is lost.

Source

Thrown at packages/core/package-manager/src/Pnpm.js:185

        logger.log({
          origin: '@parcel/package-manager',
          message: `Added ${addedCount} ${
            removedCount > 0 ? `and removed ${removedCount} ` : ''
          }packages via pnpm`,
        });
      }

      // Since we succeeded, stderr might have useful information not included
      // in the json written to stdout. It's also not necessary to log these as
      // errors as they often aren't.
      for (let message of stderr) {
        logger.log({
          origin: '@parcel/package-manager',
          message,
        });
      }
    } catch (e) {
      throw new Error('pnpm failed to install modules');
    }
  }
}

function prefix(message: string): string {
  return 'pnpm: ' + message;
}

registerSerializableClass(`${pkg.version}:Pnpm`, Pnpm);

View on GitHub (pinned to 59484858a1)

Solutions

  1. Run `pnpm install` manually in the terminal to see the actual error output (the Parcel wrapper swallows it).
  2. Delete pnpm-lock.yaml and node_modules, then retry.
  3. Clear the pnpm store: `pnpm store prune`.
  4. Check pnpm version compatibility: `pnpm --version` and update if needed.
  5. Report the lossy error message as a bug — the catch block should include e.message like the Npm and Yarn wrappers do.

Example fix

// before: error message has no details
// Error: pnpm failed to install modules

// after: run manually to see real error
// $ cd <project-root> && pnpm install
// then fix the underlying issue shown in pnpm's own output
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: verify pnpm is available and store is healthy
const {execSync} = require('child_process');

function preflightPnpm() {
  try {
    let version = execSync('pnpm --version', {encoding: 'utf8'}).trim();
    if (!version) throw new Error('pnpm not found');
  } catch {
    throw new Error('pnpm is not installed or not on PATH');
  }
}

Try / catch

try {
  await pnpmInstaller.install({modules, saveDev, cwd, packagePath, fs});
} catch (e) {
  if (e.message === 'pnpm failed to install modules') {
    // Error message is lossy — run pnpm manually for details
    console.error('Run "pnpm install" manually to see the actual error');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: install() is called on the Pnpm class, which spawns `pnpm install` as a child process. The promise from the process rejects (non-zero exit), and the catch block re-throws a generic message without the original error. The stderr was processed in the success path's loop but is not accessible in the catch block.

Common situations: pnpm store corruption or lockfile conflicts. Network issues reaching the registry. pnpm version incompatibility with the lockfile format. Permission errors on the pnpm store directory. Hoisting conflicts in a monorepo workspace.

Related errors


AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13). Data as JSON: /api/errors/22762e4b4c8150d5. Report an issue: GitHub.