affaan-m/ECC · error · Error

Invalid Claude hooks preference: ${claudeHooks}

Error message

Invalid Claude hooks preference: ${claudeHooks}

What it means

When Claude is selected, claudeHooks must be one of off, minimal, standard, or strict (VALID_CLAUDE_HOOKS). These pick which bundled hook profile gets installed alongside the plugin. Any other value is rejected to prevent installing an unknown hook set. The check only fires when Claude is selected; otherwise claudeHooks is undefined.

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 01e15490f0)

Solutions

  1. Use one of the four valid values: 'off' (no hooks), 'minimal', 'standard' (default), or 'strict'.
  2. Omit claudeHooks to accept the default ('standard').
  3. Check for the common synonyms that are NOT accepted: 'none' -> 'off', 'default' -> 'standard', 'all'/'max' -> 'strict'.
  4. Verify spelling and case — values are matched exactly against the lowercase set.

Example fix

// before
normalizeGuidedInstallRequest({ harnesses: ['claude'], claudeHooks: 'none' }); // throws
// after
normalizeGuidedInstallRequest({ harnesses: ['claude'], claudeHooks: 'off' });
// or omit for the default
normalizeGuidedInstallRequest({ harnesses: ['claude'] }); // claudeHooks = 'standard'
Defensive patterns

Strategy: validation

Validate before calling

const { VALID_CLAUDE_HOOKS } = require('./scripts/lib/multi-harness-setup');
function assertClaudeHooks(value) {
  if (value !== undefined && !VALID_CLAUDE_HOOKS.has(value)) {
    throw new Error(`Invalid Claude hooks preference: ${value}`);
  }
  return value;
}

Type guard

function isValidClaudeHooks(v) {
  return v === undefined || new Set(['off','minimal','standard','strict']).has(v);
}

Try / catch

try { normalizeGuidedInstallRequest(input); }
catch (error) {
  if (/Invalid Claude hooks preference/i.test(error.message)) {
    console.error('claudeHooks must be one of: off, minimal, standard, strict.');
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling normalizeGuidedInstallRequest with harnesses including 'claude' and a claudeHooks value outside {off, minimal, standard, strict}. Examples: 'none', 'all', 'default', 'aggressive', an empty string.

Common situations: Typing the hook level; assuming 'none' is valid (it is 'off'); passing 'default' (it is 'standard'); stale naming from a prior version; a UI dropdown listing the wrong values; copy-paste from docs that used a different term.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/5f8e826e1ecc2008. Report an issue: GitHub.