angular/angular-cli · error · PackageManagerError

${parsedError.summary}

Error message

${parsedError.summary}

What it means

PackageManagerError wrapping a structured error that the package manager (npm/pnpm/yarn) printed in its own output. In #fetchAndParse, after running a command like `npm view` or `yarn info`, the descriptor's output parser scans stdout/stderr for a known structured error pattern. If one is found and it is not classified as a 'not found' (E404-style, which returns null instead), the CLI throws a PackageManagerError whose message is the parsed summary, carrying the raw stdout, stderr, and exit code. This is the Angular CLI surfacing the package manager's own failure rather than silently continuing.

Source

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

    const getError = this.descriptor.outputParsers.getError;
    const parsedError =
      getError?.(stdout, this.options.logger) ?? getError?.(stderr, this.options.logger) ?? null;

    if (parsedError) {
      this.options.logger?.debug(
        `[${this.descriptor.binary}] Structured error (code: ${parsedError.code}): ${parsedError.summary}`,
      );

      // Special case for 'not found' errors (e.g., E404). Return null for these.
      if (this.descriptor.isNotFound(parsedError)) {
        if (cache && cacheKey) {
          cache.set(cacheKey, null);
        }

        return null;
      } else {
        // For all other structured errors, throw a more informative error.
        throw new PackageManagerError(parsedError.summary, stdout, stderr, exitCode);
      }
    }

    // If an error was originally thrown and we didn't parse a more specific
    // 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;

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Read the error's stdout/stderr fields to see the underlying package manager message and fix the root cause (network, auth, registry URL).
  2. Verify connectivity to the configured registry: `npm ping` or `curl <registry-url>`; fix proxy/VPN settings if it fails.
  3. Check .npmrc/.yarnrc registry and auth configuration; ensure the auth token is valid and scoped to the right registry.
  4. Clear the package manager cache (`npm cache verify` / `yarn cache clean`) if output suggests corruption.
  5. Retry with an explicit `registry` option pointing at a known-good registry to rule out local misconfiguration.

Example fix

// before: unhandled failure in CI
const metadata = await pm.getRegistryMetadata('@myorg/private-pkg');

// after: handle registry/network failures explicitly
let metadata;
try {
  metadata = await pm.getRegistryMetadata('@myorg/private-pkg');
} catch (e) {
  if (e instanceof PackageManagerError) {
    logger.error(`Registry command failed (exit ${e.exitCode}): ${e.stderr}`);
    metadata = null; // fall back to local resolution
  } 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);
// Pre-flight: confirm the registry is reachable before calling library methods
await run('npm ping'); // throws if registry unreachable/auth fails

Type guard

function isPackageManagerError(e: unknown): e is PackageManagerError {
  return e instanceof PackageManagerError
    && typeof e.exitCode === 'number'
    && typeof e.stdout === 'string'
    && typeof e.stderr === 'string';
}

Try / catch

try {
  const metadata = await pm.getRegistryMetadata(name);
} catch (e) {
  if (isPackageManagerError(e)) {
    logger.error(`Package manager failed (exit ${e.exitCode}):\n${e.stderr || e.stdout}`);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling dependencies(), getRegistryMetadata(), manifest(), or any method that routes through #fetchAndParse, when the underlying package manager command exits non-zero (or prints a structured error, e.g. Yarn classic exiting 0 with an error block) with an error other than 'package not found' — e.g. network failures, registry auth errors, invalid arguments.

Common situations: Corporate proxy or offline machine blocking registry access; misconfigured .npmrc/.yarnrc registry URL; private package requiring auth token; corrupted npm cache; running behind a firewall; npm/yarn printing ECONNREFUSED, ETIMEDOUT, or 401/403 responses.

Related errors


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