{"record":{"id":"baee7174a27469cb","repo":"affaan-m/ECC","slug":"install-module-moduleid-has-unsupported-targets","errorCode":null,"errorMessage":"Install module ${moduleId} has unsupported targets: ${unsupportedTargets.join(', ')}","messagePattern":"Install module (.+?) has unsupported targets: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/install-manifests.js","lineNumber":244,"sourceCode":"function readModuleTargetsOrThrow(module) {\n  const moduleId = module && module.id ? module.id : '<unknown>';\n  const targets = module && module.targets;\n\n  if (!Array.isArray(targets)) {\n    throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);\n  }\n\n  const normalizedTargets = targets.map(target => (\n    typeof target === 'string' ? target.trim() : ''\n  ));\n\n  if (normalizedTargets.some(target => target.length === 0)) {\n    throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);\n  }\n\n  const unsupportedTargets = normalizedTargets.filter(target => !SUPPORTED_INSTALL_TARGETS.includes(target));\n  if (unsupportedTargets.length > 0) {\n    throw new Error(\n      `Install module ${moduleId} has unsupported targets: ${unsupportedTargets.join(', ')}`\n    );\n  }\n\n  return normalizedTargets;\n}\n\nfunction assertKnownModuleIds(moduleIds, manifests) {\n  const unknownModuleIds = dedupeStrings(moduleIds)\n    .filter(moduleId => !manifests.modulesById.has(moduleId));\n\n  if (unknownModuleIds.length === 1) {\n    throw new Error(`Unknown install module: ${unknownModuleIds[0]}`);\n  }\n\n  if (unknownModuleIds.length > 1) {\n    throw new Error(`Unknown install modules: ${unknownModuleIds.join(', ')}`);\n  }","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/install-manifests.js#L226-L262","documentation":"After normalisation, every target id must be in SUPPORTED_INSTALL_TARGETS (claude, claude-project, cursor, antigravity, codex, gemini, opencode, codebuddy, joycode, qwen, zed, hermes, openclaw, kimi). Any target not in that list is collected into unsupportedTargets and the whole module is rejected with the offending ids listed.","triggerScenarios":"install-modules.json declares a target the installer does not recognise — typo ('Cluade'), removed id ('vscodium'), or a forward reference to a target added in a newer installer version. Triggered at manifest load for any module consumed by the install pipeline.","commonSituations":"Author added a new target id but the running installer predates it; renamed target id (old name still in manifest); case mismatch ('Claude' vs 'claude'); copy-paste from another harness's docs.","solutions":["Compare each id in the message against SUPPORTED_INSTALL_TARGETS (case-sensitive, lowercase, hyphenated).","Fix typos and casing in manifests/install-modules.json.","If the id is genuinely new, upgrade the installer package so SUPPORTED_INSTALL_TARGETS includes it.","Remove targets the installer cannot service rather than leaving stale ids."],"exampleFix":"// before: { \"id\": \"my-mod\", \"targets\": [\"claude\", \"Cluade\"] }\n// after: { \"id\": \"my-mod\", \"targets\": [\"claude\"] }","handlingStrategy":"validation","validationCode":"const SUPPORTED = new Set(['claude','claude-project','cursor','antigravity','codex','gemini','opencode','codebuddy','joycode','qwen','zed','hermes','openclaw','kimi']);\nfunction unsupportedModuleTargets(module) {\n  return (module.targets || []).filter(t => !SUPPORTED.has(t));\n}\n// before load: assert manifests.modules.every(m => unsupportedModuleTargets(m).length === 0)","typeGuard":"function isSupportedTarget(value) {\n  return SUPPORTED.has(value);\n}","tryCatchPattern":"try {\n  loadInstallManifests({ repoRoot });\n} catch (err) {\n  if (/has unsupported targets/.test(err.message)) {\n    // extract ids from message, fix manifest, retry\n  } else throw err;\n}","preventionTips":["Keep the manifest's target list in sync with SUPPORTED_INSTALL_TARGETS for the shipping installer version.","Add a CI check that diffs declared targets against the constant.","Avoid forward-referencing target ids before the installer supports them.","Prefer lowercase hyphenated ids; reject PRs that introduce case variants."],"tags":["manifest","validation","install","targets"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}