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

  1. Use one of the valid hooks preferences defined in VALID_CLAUDE_HOOKS (e.g. 'standard', 'strict')
  2. Omit claudeHooks to fall back to the 'standard' default
  3. 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

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


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)