affaan-m/ECC · error · Error

An install component ID is required

Error message

An install component ID is required

What it means

Thrown by getInstallComponent() when the supplied componentId normalizes to an empty string after String(componentId || '').trim(). The function refuses to look up an empty key because the componentsById Map cannot meaningfully resolve one. It is a programmer-error guard, not an environmental condition.

Source

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

      return {
        id: component.id,
        family: component.family,
        description: component.description,
        moduleIds,
        moduleCount: moduleIds.length,
        targets,
      };
    })
    .filter(component => !target || component.targets.includes(target));
}

function getInstallComponent(componentId, options = {}) {
  const manifests = loadInstallManifests(options);
  const normalizedComponentId = String(componentId || '').trim();

  if (!normalizedComponentId) {
    throw new Error('An install component ID is required');
  }

  const component = manifests.componentsById.get(normalizedComponentId);
  if (!component) {
    throw new Error(`Unknown install component: ${normalizedComponentId}`);
  }

  const moduleIds = dedupeStrings(component.modules);
  const modules = moduleIds
    .map(moduleId => manifests.modulesById.get(moduleId))
    .filter(Boolean)
    .map(module => ({
      id: module.id,
      kind: module.kind,
      description: module.description,
      targets: module.targets,
      defaultInstall: module.defaultInstall,
      cost: module.cost,

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Pass a non-empty component ID such as 'skill:tdd-workflow' or 'lang:rust'.
  2. If the value comes from user input, validate it before calling: if (!id || !id.trim()) return skip.
  3. Use listInstallComponents() to enumerate the valid IDs the user can choose from.
  4. When wiring a CLI flag, treat a missing --component as a usage error with a help message, not as a silent call.

Example fix

// before
const info = getInstallComponent(req.query.component);
// after
const id = String(req.query.component || '').trim();
if (!id) {
  throw new Error('Usage: ?component=<id>. Run list to see options.');
}
const info = getInstallComponent(id);
Defensive patterns

Strategy: validation

Validate before calling

const id = String(componentId || '').trim();
if (!id) {
  throw new TypeError('componentId must be a non-empty string');
}
const info = getInstallComponent(id);

Type guard

/** @param {unknown} v */
function isNonEmptyComponentId(v) {
  return typeof v === 'string' && v.trim().length > 0;
}

Prevention

When it happens

Trigger: Calling getInstallComponent(undefined), getInstallComponent(''), getInstallComponent(' '), getInstallComponent(null), or getInstallComponent(0) — anything that is falsy or trims to zero length.

Common situations: CLI flag --component was not passed; a caller destructured the wrong field from a config object; an upstream variable defaulted to undefined; a script loops over a list and one entry is an empty string.

Related errors


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