angular/angular-cli · error · PackageManagerError

Failed to parse package manager output: ${e instanceof Error

Error message

Failed to parse package manager output: ${e instanceof Error ? e.message : ''}

What it means

Thrown when the package manager command succeeded (exit 0, no structured error parsed) but the CLI's parser for that package manager's output threw — usually because stdout was not the expected JSON/structured format. #fetchAndParse wraps any parser exception in a PackageManagerError with the message 'Failed to parse package manager output: <original message>' plus the raw stdout/stderr/exitCode, so the caller can inspect what the tool actually printed.

Source

Thrown at packages/angular/cli/src/package-managers/package-manager.ts:322

    // structured error, re-throw the original error now.
    if (thrownError) {
      throw thrownError;
    }

    // If we reach this point, the command succeeded and no structured error was found.
    // We can now safely parse the successful output.
    try {
      const result = parser(stdout, this.options.logger);
      if (cache && cacheKey) {
        cache.set(cacheKey, result);
      }

      return result;
    } catch (e) {
      const message = `Failed to parse package manager output: ${
        e instanceof Error ? e.message : ''
      }`;
      throw new PackageManagerError(message, stdout, stderr, exitCode);
    }
  }

  /**
   * Adds a package to the project's dependencies.
   * @param packageName The name of the package to add.
   * @param save The save strategy to use.
   * - `exact`: The package will be saved with an exact version.
   * - `tilde`: The package will be saved with a tilde version range (`~`).
   * - `none`: The package will be saved with the default version range (`^`).
   * @param asDevDependency Whether to install the package as a dev dependency.
   * @param noLockfile Whether to skip updating the lockfile.
   * @param options Extra options for the command.
   * @returns A promise that resolves when the command is complete.
   */
  async add(
    packageName: string,
    save: 'exact' | 'tilde' | 'none',

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Inspect e.stdout/e.stderr on the PackageManagerError to see what the package manager actually printed, then fix whatever polluted the output.
  2. Verify the package manager binary works directly: run the equivalent `npm view <pkg> --json` / `yarn info` command manually and check it prints valid JSON.
  3. Check for shell wrappers, aliases, or npm config (`.npmrc` settings like `loglevel`, `progress`, `fund`, `audit`) that add non-JSON text to stdout.
  4. Confirm the installed package manager version is supported by the Angular CLI and not a heavily modified fork.
  5. Free disk space / increase available memory if stdout appears truncated.

Example fix

// before: debug via opaque failure
const manifest = await pm.getManifest('lodash@^4');

// after: surface the raw output on parse failure
try {
  const manifest = await pm.getManifest('lodash@^4');
} catch (e) {
  if (e instanceof PackageManagerError && e.message.startsWith('Failed to parse package manager output')) {
    console.error('Raw stdout was:', e.stdout);
    // e.g. reveals an npm notice/banner breaking JSON.parse
  } else {
    throw e;
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { exec } from 'node:child_process';
import { promisify } from 'node:util';
const run = promisify(exec);
// Verify the package manager emits clean JSON before using library methods
const { stdout } = await run('npm view lodash name --json');
JSON.parse(stdout); // throws early if output is polluted/non-JSON

Type guard

function isOutputParseError(e: unknown): e is PackageManagerError {
  return e instanceof PackageManagerError
    && e.message.startsWith('Failed to parse package manager output');
}

Try / catch

try {
  const deps = await pm.dependencies();
} catch (e) {
  if (isOutputParseError(e)) {
    console.error('Unexpected tool output:', JSON.stringify({ stdout: e.stdout, stderr: e.stderr }, null, 2));
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling dependencies(), getRegistryMetadata(), or manifest() where the output parser (e.g. getRegistryMetadata/getRegistryManifest parsers) calls JSON.parse or accesses expected fields on stdout that is empty, truncated, a warning banner, or human-readable text instead of machine-readable output.

Common situations: npm/yarn wrapper scripts or shell aliases injecting extra output; a global npm config (e.g. `loglevel`, `--json` overridden, init banner) polluting stdout; registry returning an HTML error page captured as output; package manager version whose output shape differs from what the CLI descriptor expects (version drift); output truncated by the OS or low disk.

Understand the failure class

Related errors


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/8b205df266a9fadf. Report an issue: GitHub.