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
- Inspect e.stdout/e.stderr on the PackageManagerError to see what the package manager actually printed, then fix whatever polluted the output.
- Verify the package manager binary works directly: run the equivalent `npm view <pkg> --json` / `yarn info` command manually and check it prints valid JSON.
- Check for shell wrappers, aliases, or npm config (`.npmrc` settings like `loglevel`, `progress`, `fund`, `audit`) that add non-JSON text to stdout.
- Confirm the installed package manager version is supported by the Angular CLI and not a heavily modified fork.
- 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
- Avoid shell aliases/wrappers around npm/yarn that print banners or notices to stdout.
- Keep the package manager version aligned with versions the Angular CLI supports; version drift changes output shapes.
- Check .npmrc for settings that append human-readable output (progress, fund, audit notices) and disable them for automation.
- Ensure sufficient disk/memory so command output is not truncated.
- When the error occurs, dump e.stdout and e.stderr — the raw output reveals exactly which extra text broke JSON parsing.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid config found at ${workspace.filePath}. CLI should be
- Invalid value for argument: ${key}, Given: '${pair}', Expect
- Invalid JSON path.
- Unsupported package manager: "${name}"
- The configured package manager, '${this.descriptor.binary}',
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/8b205df266a9fadf.
Report an issue: GitHub.