angular/angular-cli · error · UnknownPackageManagerException

Unknown package manager "${options.packageManager}".

Error message

Unknown package manager "${options.packageManager}".

What it means

Same exception family as the factory-level check, but raised inside the returned executor: when factoryOptions.allowPackageManagerOverride is true and options.packageManager is provided, the per-task manager name is looked up in packageManagers; an unknown value throws UnknownPackageManagerException.

Source

Thrown at packages/angular_devkit/schematics/tasks/package-manager/executor.ts:73

export default function (
  factoryOptions: NodePackageTaskFactoryOptions = {},
): TaskExecutor<NodePackageTaskOptions> {
  const packageManagerName = factoryOptions.packageManager || 'npm';
  const packageManagerProfile = packageManagers[packageManagerName];
  if (!packageManagerProfile) {
    throw new UnknownPackageManagerException(packageManagerName);
  }

  const rootDirectory = factoryOptions.rootDirectory || process.cwd();

  return (options: NodePackageTaskOptions = { command: 'install' }) => {
    let taskPackageManagerProfile = packageManagerProfile;
    let taskPackageManagerName = packageManagerName;
    if (factoryOptions.allowPackageManagerOverride && options.packageManager) {
      taskPackageManagerProfile = packageManagers[options.packageManager];
      if (!taskPackageManagerProfile) {
        throw new UnknownPackageManagerException(options.packageManager);
      }
      taskPackageManagerName = options.packageManager;
    }

    const bufferedOutput: { stream: NodeJS.WriteStream; data: Buffer }[] = [];
    const spawnOptions: SpawnOptions = {
      shell: true,
      cwd: path.join(rootDirectory, options.workingDirectory || ''),
    };
    if (options.hideOutput) {
      spawnOptions.stdio = options.quiet ? ['ignore', 'ignore', 'pipe'] : 'pipe';
    } else {
      spawnOptions.stdio = options.quiet ? ['ignore', 'ignore', 'inherit'] : 'inherit';
    }

    const args: string[] = [];

    if (options.packageName) {

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Use a supported options.packageManager value ('npm', 'yarn', 'pnpm')
  2. Remove options.packageManager from the task options so the factory default is used
  3. Upgrade the devkit to a version whose packageManagers map includes your manager
  4. Validate user input before scheduling the task

Example fix

// before
context.addTask(new NodePackageTask({ command: 'install', packageManager: 'bun' }));
// after
context.addTask(new NodePackageTask({ command: 'install', packageManager: 'pnpm' }));
Defensive patterns

Strategy: validation

Validate before calling

const supported = ['npm', 'yarn', 'pnpm'];
if (options.packageManager && !supported.includes(options.packageManager)) {
  throw new Error(`Unsupported package manager option: ${options.packageManager}`);
}

Type guard

type PackageManager = 'npm' | 'yarn' | 'pnpm';
function isPackageManagerOption(o: unknown): o is { packageManager: PackageManager } {
  const v = o as { packageManager?: unknown };
  return typeof v.packageManager === 'string' &&
    ['npm', 'yarn', 'pnpm'].includes(v.packageManager);
}

Try / catch

try {
  await executor({ command: 'install', packageManager: userChoice });
} catch (e) {
  if (/Unknown package manager/.test(String(e))) {
    await executor({ command: 'install' }); // fall back to default
  } else throw e;
}

Prevention

When it happens

Trigger: Scheduling a NodePackage task with options.packageManager set (e.g. { command: 'install', packageManager: 'bun' }) while allowPackageManagerOverride is enabled and the name isn't in the supported map.

Common situations: Schematics/tasks that let users pick the install command's manager; CI configs injecting packageManager into task options; newer manager names on older toolchains; typos in task options.

Related errors


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