{"record":{"id":"1ac779576f31de37","repo":"angular/angular-cli","slug":"parsederror-summary","errorCode":null,"errorMessage":"${parsedError.summary}","messagePattern":"\\$\\{parsedError\\.summary\\}","errorType":"exception","errorClass":"PackageManagerError","httpStatus":null,"severity":"error","filePath":"packages/angular/cli/src/package-managers/package-manager.ts","lineNumber":299,"sourceCode":"    const getError = this.descriptor.outputParsers.getError;\n    const parsedError =\n      getError?.(stdout, this.options.logger) ?? getError?.(stderr, this.options.logger) ?? null;\n\n    if (parsedError) {\n      this.options.logger?.debug(\n        `[${this.descriptor.binary}] Structured error (code: ${parsedError.code}): ${parsedError.summary}`,\n      );\n\n      // Special case for 'not found' errors (e.g., E404). Return null for these.\n      if (this.descriptor.isNotFound(parsedError)) {\n        if (cache && cacheKey) {\n          cache.set(cacheKey, null);\n        }\n\n        return null;\n      } else {\n        // For all other structured errors, throw a more informative error.\n        throw new PackageManagerError(parsedError.summary, stdout, stderr, exitCode);\n      }\n    }\n\n    // If an error was originally thrown and we didn't parse a more specific\n    // structured error, re-throw the original error now.\n    if (thrownError) {\n      throw thrownError;\n    }\n\n    // If we reach this point, the command succeeded and no structured error was found.\n    // We can now safely parse the successful output.\n    try {\n      const result = parser(stdout, this.options.logger);\n      if (cache && cacheKey) {\n        cache.set(cacheKey, result);\n      }\n\n      return result;","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/cli/src/package-managers/package-manager.ts#L281-L317","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the error's stdout/stderr fields to see the underlying package manager message and fix the root cause (network, auth, registry URL).","Verify connectivity to the configured registry: `npm ping` or `curl <registry-url>`; fix proxy/VPN settings if it fails.","Check .npmrc/.yarnrc registry and auth configuration; ensure the auth token is valid and scoped to the right registry.","Clear the package manager cache (`npm cache verify` / `yarn cache clean`) if output suggests corruption.","Retry with an explicit `registry` option pointing at a known-good registry to rule out local misconfiguration."],"exampleFix":"// before: unhandled failure in CI\nconst metadata = await pm.getRegistryMetadata('@myorg/private-pkg');\n\n// after: handle registry/network failures explicitly\nlet metadata;\ntry {\n  metadata = await pm.getRegistryMetadata('@myorg/private-pkg');\n} catch (e) {\n  if (e instanceof PackageManagerError) {\n    logger.error(`Registry command failed (exit ${e.exitCode}): ${e.stderr}`);\n    metadata = null; // fall back to local resolution\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":"import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nconst run = promisify(exec);\n// Pre-flight: confirm the registry is reachable before calling library methods\nawait run('npm ping'); // throws if registry unreachable/auth fails","typeGuard":"function isPackageManagerError(e: unknown): e is PackageManagerError {\n  return e instanceof PackageManagerError\n    && typeof e.exitCode === 'number'\n    && typeof e.stdout === 'string'\n    && typeof e.stderr === 'string';\n}","tryCatchPattern":"try {\n  const metadata = await pm.getRegistryMetadata(name);\n} catch (e) {\n  if (isPackageManagerError(e)) {\n    logger.error(`Package manager failed (exit ${e.exitCode}):\\n${e.stderr || e.stdout}`);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Run `npm ping` (or the equivalent for yarn/pnpm) in setup/CI steps to validate registry connectivity early.","Keep .npmrc/.yarnrc registry and auth token configuration valid and scoped to the correct registry host.","Handle E404 separately: those return null from the library instead of throwing, so treat null as 'not found' not 'error'.","Log PackageManagerError's stdout/stderr/exitCode fields — they contain the underlying tool's own diagnosis.","Retry transient network failures with backoff before giving up."],"tags":["package-manager","network","registry","angular-cli"],"backgroundTag":"package-manager-registry-error","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}