affaan-m/ECC · error · Error

Unknown package manager: ${pmName}

Error message

Unknown package manager: ${pmName}

What it means

Thrown by setPreferredPackageManager when pmName is not a key of PACKAGE_MANAGERS. The package-manager module only recognizes npm, pnpm, yarn, and bun; any other value (typos, case variants, retired managers) is rejected before touching global config. This is the input-validation gate for the global setter, distinct from the project-level setter which throws the same message at a different call site.

Source

Thrown at scripts/lib/package-manager.js:246

  // NOTE: Previously this called getAvailablePackageManagers() which spawns
  // child processes (where.exe/which) for each PM. This caused plugin freezes
  // on Windows (see #162) because session-start hooks run during Bun init,
  // and the spawned processes exceed Bun's spawn limit.
  // Steps 1-5 already cover all config-based and file-based detection.
  // If none matched, npm is the safe default.
  return {
    name: 'npm',
    config: PACKAGE_MANAGERS.npm,
    source: 'default'
  };
}

/**
 * Set user's preferred package manager (global)
 */
function setPreferredPackageManager(pmName) {
  if (!PACKAGE_MANAGERS[pmName]) {
    throw new Error(`Unknown package manager: ${pmName}`);
  }

  const config = loadConfig() || {};
  config.packageManager = pmName;
  config.setAt = new Date().toISOString();

  try {
    saveConfig(config);
  } catch (err) {
    throw new Error(`Failed to save package manager preference: ${err.message}`);
  }

  return config;
}

/**
 * Set project's preferred package manager
 */

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Pass one of: 'npm', 'pnpm', 'yarn', 'bun' (lowercase, no version).
  2. Strip any '@version' suffix before calling: pmName.split('@')[0].
  3. Lowercase the input: pmName.toLowerCase().
  4. Source the value from Object.keys(PACKAGE_MANAGERS) in a menu rather than free-text.

Example fix

// before
setPreferredPackageManager('pnpm@8'); // throws [296]
setPreferredPackageManager('Yarn');    // throws [296]

// after
setPreferredPackageManager('pnpm');
setPreferredPackageManager('yarn');
Defensive patterns

Strategy: validation

Validate before calling

const { PACKAGE_MANAGERS } = require('./scripts/lib/package-manager');
function assertKnownPm(pmName) {
  if (!PACKAGE_MANAGERS[pmName]) {
    throw new Error(`Unknown package manager '${pmName}'. Allowed: ${Object.keys(PACKAGE_MANAGERS).join(', ')}`);
  }
}
assertKnownPm(pmName);
setPreferredPackageManager(pmName);

Type guard

function isSupportedPackageManager(name) {
  return name === 'npm' || name === 'pnpm' || name === 'yarn' || name === 'bun';
}

Try / catch

try {
  setPreferredPackageManager(pmName);
} catch (err) {
  if (/Unknown package manager/.test(err.message)) {
    const cleaned = String(pmName).toLowerCase().split('@')[0];
    if (isSupportedPackageManager(cleaned)) setPreferredPackageManager(cleaned);
    else throw err;
  } else throw err;
}

Prevention

When it happens

Trigger: Fires when PACKAGE_MANAGERS[pmName] is undefined in setPreferredPackageManager. Reached by calling setPreferredPackageManager('pnpm' typo'd as 'pnmp'), with wrong case ('Npm'), with a retired manager name, or with an empty/non-string value that is not a key.

Common situations: Typo in the manager name; case sensitivity ('Yarn' vs 'yarn'); passing a versioned string like 'pnpm@8' (the setter wants the bare name, unlike package.json's packageManager field); shell variable expansion producing an empty string; user typing a manager ECC does not support (e.g., 'volta').

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/69cef61866603d92. Report an issue: GitHub.