parcel-bundler/parcel · error · Error

Failed to install ${moduleNames}: ${err.message}

Error message

Failed to install ${moduleNames}: ${err.message}

What it means

Thrown by installPackage() when the determined package installer's install() method throws. This is a generic wrapper around any installer (npm, yarn, or pnpm). The error message includes the module names being installed and the underlying installer's error message. This function is called by NodePackageManager.resolve() during auto-install and by installPeerDependencies.

Source

Thrown at packages/core/package-manager/src/installPackage.js:66

    ['package.json'],
    projectRoot,
  );
  let cwd = fromPkgPath ? path.dirname(fromPkgPath) : fs.cwd();

  if (!packageInstaller) {
    packageInstaller = await determinePackageInstaller(fs, from, projectRoot);
  }

  try {
    await packageInstaller.install({
      modules,
      saveDev,
      cwd,
      packagePath: fromPkgPath,
      fs,
    });
  } catch (err) {
    throw new Error(`Failed to install ${moduleNames}: ${err.message}`);
  }

  if (installPeers) {
    await Promise.all(
      modules.map(m =>
        installPeerDependencies(
          fs,
          packageManager,
          m,
          from,
          projectRoot,
          options,
        ),
      ),
    );
  }
}

View on GitHub (pinned to 59484858a1)

Solutions

  1. Read the inner err.message in the thrown error — it contains the installer-specific reason.
  2. Install the package manually with the correct package manager: `npm install <module>` or `yarn add <module>`.
  3. Disable auto-install if it's causing repeated failures: set `shouldAutoInstall: false` in Parcel config.
  4. Ensure only one package manager is used — remove conflicting lockfiles (package-lock.json AND yarn.lock AND pnpm-lock.yaml).

Example fix

// before: auto-install fails during build
// Error: Failed to install react: EACCES permission denied

// after: install manually beforehand
// $ npm install react
// then run parcel build
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: verify modules exist on registry before install
const {execSync} = require('child_process');

function moduleExists(name) {
  try {
    execSync(`npm view ${name} version`, {stdio: 'pipe', timeout: 10000});
    return true;
  } catch {
    return false;
  }
}

for (let mod of modules) {
  if (!moduleExists(mod.name)) {
    throw new Error(`Package '${mod.name}' does not exist on the registry`);
  }
}

Try / catch

try {
  await installPackage(fs, packageManager, modules, from, projectRoot, options);
} catch (e) {
  if (e.message.startsWith('Failed to install')) {
    // Extract module names and inner error
    let match = e.message.match(/Failed to install (.*): (.*)/);
    if (match) {
      console.error(`Install of ${match[1]} failed: ${match[2]}`);
    }
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: installPackage() calls packageInstaller.install() with the modules, saveDev flag, cwd, and packagePath. Any rejection from that promise is caught and re-wrapped with context about which modules failed. The determinePackageInstaller call selects npm/yarn/pnpm based on lockfile detection.

Common situations: Auto-install triggered by Parcel's shouldAutoInstall option fails because the package doesn't exist on the registry. Permission errors writing to node_modules. Package name typo causing a 404. SaveDev flag causes package.json write permission errors. Mixed package managers (yarn.lock present but npm is called).

Related errors


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