affaan-m/ECC · error · Error
Invalid Claude hooks preference
Error message
Invalid Claude hooks preference: ${claudeHooks} What it means
normalizeGuidedInstallRequest validates the resolved claudeHooks preference (defaulting to 'standard') against the VALID_CLAUDE_HOOKS whitelist. An unrecognized hooks preference string throws this error with the offending value. It protects against misspelled hook profiles that would otherwise be silently ignored or misapplied.
Solutions
- Use one of the valid hooks preferences defined in VALID_CLAUDE_HOOKS (e.g. 'standard', 'strict')
- Omit claudeHooks to fall back to the 'standard' default
- Validate the value against VALID_CLAUDE_HOOKS before constructing the request
Example fix
// before
runSetup({ harnesses: ['claude'], claudeHooks: 'aggressive' })
// after
runSetup({ harnesses: ['claude'], claudeHooks: 'strict' }) Defensive patterns
Strategy: validation
Validate before calling
const VALID_HOOKS = ['standard', 'strict'] // confirm against VALID_CLAUDE_HOOKS in the library
if (input.claudeHooks !== undefined && !VALID_HOOKS.includes(input.claudeHooks)) {
throw new Error(`claudeHooks must be one of: ${VALID_HOOKS.join(', ')}`)
} Type guard
const isValidHooksPref = (s) => typeof s === 'string' && ['standard', 'strict'].includes(s)
Try / catch
try {
return normalizeGuidedInstallRequest(input)
} catch (err) {
if (err.message.startsWith('Invalid Claude hooks preference:')) {
return normalizeGuidedInstallRequest({ ...input, claudeHooks: 'standard' })
}
throw err
} Prevention
- Restrict interactive prompts/CLI flags to the library's valid hooks values
- Default to omitting claudeHooks so the 'standard' default applies
- Check changelogs for hooks-tier renames after upgrading the library
When it happens
Trigger: Calling the guided install request API with input.claudeHooks set to a string not present in VALID_CLAUDE_HOOKS (e.g. 'strict-hooks', 'off', or a casing/typo variant of a valid value like 'standard'/'strict').
Common situations: Typo in CLI flag or script; copying a hooks level name from another project with different tiers; passing free-form strings from an interactive prompt without validating against the allowed set.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid managed hook handler at
- artifact has invalid modality binding
- assigneeKind must be 'agent' or 'human'.
- CV effect has an invalid subject anchor
- explicit candidate review state required
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/5f8e826e1ecc2008.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/multi-harness-setup.js:42
}
const includesClaude = harnesses.includes('claude');
const includesKimi = harnesses.includes('kimi');
if (!includesClaude && (input.claudeScope !== undefined || input.claudeHooks !== undefined)) {
throw new Error('Claude scope and hook options require Claude to be selected.');
}
if (!includesKimi && input.profile !== undefined) {
throw new Error('The managed install profile requires Kimi to be selected.');
}
const claudeScope = includesClaude ? (input.claudeScope || 'user') : undefined;
const claudeHooks = includesClaude ? (input.claudeHooks || 'standard') : undefined;
const profile = includesKimi ? (input.profile || 'core') : undefined;
if (claudeScope && !VALID_CLAUDE_SCOPES.has(claudeScope)) {
throw new Error(`Invalid Claude scope: ${claudeScope}`);
}
if (claudeHooks && !VALID_CLAUDE_HOOKS.has(claudeHooks)) {
throw new Error(`Invalid Claude hooks preference: ${claudeHooks}`);
}
if (profile && !VALID_PROFILES.has(profile)) {
throw new Error(`Invalid Kimi install profile: ${profile}`);
}
return {
harnesses,
...(claudeHooks ? { claudeHooks } : {}),
...(claudeScope ? { claudeScope } : {}),
dryRun: Boolean(input.dryRun),
json: Boolean(input.json),
...(profile ? { profile } : {}),
yes: Boolean(input.yes),
};
}
function canonicalPath(filePath) {
return realpathNearestExisting(filePath);View on GitHub (pinned to 8321021c54)