affaan-m/ECC · error · Error
Install module ${moduleId} has invalid targets; expected an
Error message
Install module ${moduleId} has invalid targets; expected an array of supported target ids What it means
readModuleTargetsOrThrow reads `module.targets` from install-modules.json. The field MUST be an array; anything else (string, object, null, undefined, number) is rejected up front. The check fires before any per-element validation, so this is specifically the wrong-shape failure.
Source
Thrown at scripts/lib/install-manifests.js:231
|| options[key] === null
|| options[key] === undefined
) {
return null;
}
if (typeof options[key] !== 'string' || options[key].trim() === '') {
throw new Error(`${key} must be a non-empty string when provided`);
}
return options[key];
}
function readModuleTargetsOrThrow(module) {
const moduleId = module && module.id ? module.id : '<unknown>';
const targets = module && module.targets;
if (!Array.isArray(targets)) {
throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);
}
const normalizedTargets = targets.map(target => (
typeof target === 'string' ? target.trim() : ''
));
if (normalizedTargets.some(target => target.length === 0)) {
throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);
}
const unsupportedTargets = normalizedTargets.filter(target => !SUPPORTED_INSTALL_TARGETS.includes(target));
if (unsupportedTargets.length > 0) {
throw new Error(
`Install module ${moduleId} has unsupported targets: ${unsupportedTargets.join(', ')}`
);
}
return normalizedTargets;View on GitHub (pinned to 01e15490f0)
Solutions
- Open manifests/install-modules.json and find the module whose id appears in the error.
- Change `targets` to an array: `"targets": ["claude"]` (not `"targets": "claude"`).
- Validate the file against the manifest schema before committing (`npm run catalog:sync` or the project's manifest validator).
- Re-run `npm test` to catch manifest shape errors locally.
Example fix
// before: { "id": "rules-core", "targets": "claude" }
// after: { "id": "rules-core", "targets": ["claude"] } Defensive patterns
Strategy: validation
Validate before calling
function moduleHasArrayTargets(module) {
return Boolean(module && Array.isArray(module.targets));
}
// when loading manifests: manifests.modules.every(moduleHasArrayTargets) Type guard
function isModuleWithArrayTargets(module) {
return Boolean(module && typeof module === 'object' && Array.isArray(module.targets));
} Try / catch
try {
loadInstallManifests({ repoRoot });
} catch (err) {
if (/has invalid targets; expected an array/.test(err.message)) {
// fix the manifest entry by id, then retry
} else throw err;
} Prevention
- Use the manifest JSON schema in editor/CI to enforce array types.
- Avoid YAML-to-JSON pipelines that collapse single-item arrays.
- Run `npm run catalog:sync` and `npm test` before committing manifest changes.
- Code-review manifest edits for shape, not just content.
When it happens
Trigger: loadInstallManifests parses install-modules.json and an entry has `targets` as a string ('claude') or an object instead of `['claude']`. Triggered at load time for any code path that reads modules (resolveInstallModules, intersectTargets, listInstallComponents).
Common situations: Manifest hand-edited and the author wrote a scalar instead of an array; YAML-to-JSON converter collapsed a single-item array to a scalar; schema-validation disabled in CI; copy-paste from docs that showed shorthand syntax.
Related errors
- Invalid ${label} at ${filePath}: expected a JSON object
- Invalid install-state (${label}): ${details}
- Install module ${moduleId} has unsupported targets: ${unsupp
- Unknown install module: ${unknownModuleIds[0]}
- Unknown install modules: ${unknownModuleIds.join(', ')}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/4427bbe3af5f54b4.
Report an issue: GitHub.