affaan-m/ECC · error

Invalid --hooks value

Error message

Invalid --hooks value: ${options.hooks}

What it means

parseArgs validates --hooks against VALID_HOOK_MODES (off, minimal, standard, strict per the help) and throws this for any other value. The hook preference is persisted to Claude user settings, so only the predefined profiles are permitted.

Solutions

  1. Use one of: --hooks off, --hooks minimal, --hooks standard, or --hooks strict.
  2. Omit --hooks to keep the current preference.
  3. Confirm valid values in `ecc setup --help` under 'Hook preferences'.

Example fix

// before
npm run setup -- --hooks none

// after
npm run setup -- --hooks off
Defensive patterns

Strategy: validation

Validate before calling

const VALID_HOOK_MODES = new Set(['off', 'minimal', 'standard', 'strict']);
if (hooksArg !== undefined && !VALID_HOOK_MODES.has(hooksArg)) {
  throw new Error(`Invalid --hooks value: ${hooksArg}`);
}

Type guard

const isValidHookMode = (v) => ['off', 'minimal', 'standard', 'strict'].includes(v);

Try / catch

try {
  await runSetup(rawArgs);
} catch (err) {
  if (/^Invalid --hooks value: /.test(err.message)) {
    console.error(`${err.message}. Use one of: off, minimal, standard, strict.`);
    process.exitCode = 2;
  } else throw err;
}

Prevention

When it happens

Trigger: Running `ecc setup --hooks none`, `ecc setup --hooks all`, `ecc setup --hooks STRICT`, or any value outside off|minimal|standard|strict.

Common situations: Guessing profile names ('none' instead of 'off', 'full' instead of 'strict'); case errors; stale documentation referencing renamed hook profiles; CI scripts with a hardcoded invalid preference.

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/dd871b5909020a59. Report an issue: GitHub.

Appendix: source

Thrown at scripts/setup.js:110

    } else if (argument === '--move-scope') {
      options.moveScope = true;
    } else if (argument === '--json') {
      options.json = true;
    } else if (argument === '--help' || argument === '-h') {
      options.help = true;
    } else {
      throw new Error(`Unknown argument: ${argument}`);
    }
  }

  if (options.mode !== undefined && options.mode !== MODE) {
    throw new Error(`Invalid setup mode: ${options.mode}. This command currently supports ${MODE}.`);
  }
  if (options.scope !== undefined && !VALID_SCOPES.has(options.scope)) {
    throw new Error(`Invalid --scope value: ${options.scope}`);
  }
  if (options.hooks !== undefined && !VALID_HOOK_MODES.has(options.hooks)) {
    throw new Error(`Invalid --hooks value: ${options.hooks}`);
  }
  if (options.moveScope && options.scope === undefined) {
    throw new Error('--move-scope requires an explicit --scope destination.');
  }
  return options;
}

function questionWithCancellation(terminal, prompt) {
  return new Promise((resolve, reject) => {
    let settled = false;
    const finish = callback => value => {
      if (settled) return;
      settled = true;
      terminal.removeListener('close', onClose);
      callback(value);
    };
    const onClose = finish(() => {
      const error = new Error('Readline was closed before an answer was received.');

View on GitHub (pinned to 8321021c54)