{"record":{"id":"e2ce0fbb815e301c","repo":"affaan-m/ECC","slug":"an-install-component-id-is-required","errorCode":null,"errorMessage":"An install component ID is required","messagePattern":"An install component ID is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/install-manifests.js","lineNumber":404,"sourceCode":"\n      return {\n        id: component.id,\n        family: component.family,\n        description: component.description,\n        moduleIds,\n        moduleCount: moduleIds.length,\n        targets,\n      };\n    })\n    .filter(component => !target || component.targets.includes(target));\n}\n\nfunction getInstallComponent(componentId, options = {}) {\n  const manifests = loadInstallManifests(options);\n  const normalizedComponentId = String(componentId || '').trim();\n\n  if (!normalizedComponentId) {\n    throw new Error('An install component ID is required');\n  }\n\n  const component = manifests.componentsById.get(normalizedComponentId);\n  if (!component) {\n    throw new Error(`Unknown install component: ${normalizedComponentId}`);\n  }\n\n  const moduleIds = dedupeStrings(component.modules);\n  const modules = moduleIds\n    .map(moduleId => manifests.modulesById.get(moduleId))\n    .filter(Boolean)\n    .map(module => ({\n      id: module.id,\n      kind: module.kind,\n      description: module.description,\n      targets: module.targets,\n      defaultInstall: module.defaultInstall,\n      cost: module.cost,","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/install-manifests.js#L386-L422","documentation":"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.","triggerScenarios":"Calling getInstallComponent(undefined), getInstallComponent(''), getInstallComponent('   '), getInstallComponent(null), or getInstallComponent(0) — anything that is falsy or trims to zero length.","commonSituations":"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.","solutions":["Pass a non-empty component ID such as 'skill:tdd-workflow' or 'lang:rust'.","If the value comes from user input, validate it before calling: if (!id || !id.trim()) return skip.","Use listInstallComponents() to enumerate the valid IDs the user can choose from.","When wiring a CLI flag, treat a missing --component as a usage error with a help message, not as a silent call."],"exampleFix":"// before\nconst info = getInstallComponent(req.query.component);\n// after\nconst id = String(req.query.component || '').trim();\nif (!id) {\n  throw new Error('Usage: ?component=<id>. Run list to see options.');\n}\nconst info = getInstallComponent(id);","handlingStrategy":"validation","validationCode":"const id = String(componentId || '').trim();\nif (!id) {\n  throw new TypeError('componentId must be a non-empty string');\n}\nconst info = getInstallComponent(id);","typeGuard":"/** @param {unknown} v */\nfunction isNonEmptyComponentId(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Treat the component id as required user input — surface a usage error at the CLI boundary, not inside the library.","Enumerate valid ids with listInstallComponents() before prompting the user."],"tags":["install","validation","programmer-error","argument"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}