affaan-m/ECC · error

Invalid managed hook handler at

Error message

Invalid managed hook handler at ${label}: invalid model

What it means

For prompt-type hooks, the optional 'model' field must be a non-empty string naming the model to use. validateHookHandler throws this error when hook.model is present but is not a non-empty string (empty, blank, number, object, array, or null).

Solutions

  1. Set model to a non-empty string model id, e.g. model:'sonnet'.
  2. Remove the model field to use the default model.
  3. Quote model ids in YAML so they stay strings.
  4. Ensure env-placeholder substitution for model names actually resolves.

Example fix

// before
{ "type": "prompt", "prompt": "Review", "model": 4.5 }
// after
{ "type": "prompt", "prompt": "Review", "model": "sonnet" }
Defensive patterns

Strategy: validation

Validate before calling

const bad = hooks.filter(h=>h.model!==undefined&&!(typeof h.model==='string'&&h.model.trim()!=='')); if (bad.length) throw new Error('model must be a non-empty string');

Type guard

const hasValidModel = (h) => h.model === undefined || (typeof h.model === 'string' && h.model.trim() !== '');

Try / catch

try { installHooks(cfg); } catch (e) { if (e.message.includes('invalid model')) { console.error('Hook model must be a non-empty string:', e.message); process.exitCode = 1; } else throw e; }

Prevention

When it happens

Trigger: validateManagedHooks encounters {type:'prompt', prompt:'x', model:''}, model:' ', model:3.5, model:{name:'haiku'}, or model:null.

Common situations: Model specified as a number ('sonnet 4.5' parsed as 4.5); empty model after stripping an env placeholder; nesting the model under an object; YAML unquoted model ids that parsed as non-strings.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/bcbc9758761820e1. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/install/claude-settings.js:123

      && (!isJsonObject(hook.headers)
        || !Object.values(hook.headers).every(value => typeof value === 'string'))
    ) {
      throw new Error(`Invalid managed hook handler at ${label}: invalid headers`);
    }
    if (
      hook.allowedEnvVars !== undefined
      && (!Array.isArray(hook.allowedEnvVars)
        || !hook.allowedEnvVars.every(isNonEmptyString))
    ) {
      throw new Error(`Invalid managed hook handler at ${label}: invalid allowedEnvVars`);
    }
    return;
  }
  if (!isNonEmptyString(hook.prompt)) {
    throw new Error(`Invalid managed hook handler at ${label}: invalid prompt`);
  }
  if (hook.model !== undefined && !isNonEmptyString(hook.model)) {
    throw new Error(`Invalid managed hook handler at ${label}: invalid model`);
  }
}

function validateManagedHooks(managedHooks, label = 'managed hooks') {
  if (!isJsonObject(managedHooks)) {
    throw new Error(`Invalid ${label}: expected a JSON object`);
  }
  if (Object.keys(managedHooks).length === 0) {
    throw new Error(`Invalid ${label}: expected at least one hook event`);
  }

  const seenIds = new Set();
  for (const [event, entries] of Object.entries(managedHooks)) {
    if (!VALID_EVENTS.has(event)) {
      throw new Error(`Invalid ${label}: unsupported hook event "${event}"`);
    }
    if (!Array.isArray(entries)) {
      throw new Error(`Invalid ${label}.${event}: expected an array`);

View on GitHub (pinned to 8321021c54)