affaan-m/ECC · error

Unknown install modules

Error message

Unknown install modules: ${unknownModuleIds.join(', ')}

What it means

Thrown by assertKnownModuleIds when two or more requested module ids are missing from the loaded manifests. It is the plural variant of the singular 'Unknown install module' error, listing all unknown ids comma-separated in the message.

Solutions

  1. Read the comma-separated unknown ids from the error and fix each one against manifests/install-modules.json.
  2. Regenerate or re-derive the id list from the current catalog (npm run catalog:sync output or the manifest itself).
  3. Remove entries for modules that were deleted in the current ECC version.
  4. If multiple ids share the same root cause (rename), apply the mapping for all of them at once.
  5. Re-run the validation entry point to confirm.

Example fix

// before
validateInstallModuleIds(['tdd-workflo', 'security-reveiw'])

// after
validateInstallModuleIds(['tdd-workflow', 'security-review'])
Defensive patterns

Strategy: validation

Validate before calling

const manifests = loadInstallManifests();
const unknown = ids.filter(id => !manifests.modulesById.has(id));
if (unknown.length >= 2) {
  throw new Error(`Multiple unknown module ids: ${unknown.join(', ')}`);
}

Type guard

function allModuleIdsKnown(ids, manifests) {
  return Array.isArray(ids) &&
    ids.length > 0 &&
    ids.every(id => typeof id === 'string' && manifests.modulesById.has(id));
}

Try / catch

try {
  validateInstallModuleIds(ids);
} catch (err) {
  if (err.message.startsWith('Unknown install modules: ')) {
    const unknown = err.message.slice('Unknown install modules: '.length).split(', ');
    console.error('Unknown ids:', unknown);
    process.exitCode = 1;
  } else throw err;
}

Prevention

When it happens

Trigger: validateInstallModuleIds() or resolveLegacyCompatibilitySelection() called with a list where at least two ids are absent from manifests.modulesById, e.g. validateInstallModuleIds(['foo', 'bar']) when neither exists in install-modules.json.

Common situations: Bulk-editing a profile and renaming several modules incorrectly; upgrading ECC where multiple modules were consolidated/renamed; script-generated id lists built from stale data; pasting an id list from another project.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/588f7ec5e48b035a. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/install-manifests.js:281

  if (unsupportedTargets.length > 0) {
    throw new Error(
      `Install module ${moduleId} has unsupported targets: ${unsupportedTargets.join(', ')}`
    );
  }

  return normalizedTargets;
}

function assertKnownModuleIds(moduleIds, manifests) {
  const unknownModuleIds = dedupeStrings(moduleIds)
    .filter(moduleId => !manifests.modulesById.has(moduleId));

  if (unknownModuleIds.length === 1) {
    throw new Error(`Unknown install module: ${unknownModuleIds[0]}`);
  }

  if (unknownModuleIds.length > 1) {
    throw new Error(`Unknown install modules: ${unknownModuleIds.join(', ')}`);
  }
}

function intersectTargets(modules) {
  if (!Array.isArray(modules) || modules.length === 0) {
    return [];
  }

  return SUPPORTED_INSTALL_TARGETS.filter(target => (
    modules.every(module => Array.isArray(module.targets) && module.targets.includes(target))
  ));
}

function getManifestPaths(repoRoot = DEFAULT_REPO_ROOT) {
  return {
    modulesPath: path.join(repoRoot, 'manifests', 'install-modules.json'),
    profilesPath: path.join(repoRoot, 'manifests', 'install-profiles.json'),
    componentsPath: path.join(repoRoot, 'manifests', 'install-components.json'),

View on GitHub (pinned to 8321021c54)