{"record":{"id":"bcbc9758761820e1","repo":"affaan-m/ECC","slug":"invalid-managed-hook-handler-at-label-invalid-model","errorCode":null,"errorMessage":"Invalid managed hook handler at ${label}: invalid model","messagePattern":"Invalid managed hook handler at (.+?): invalid model","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install/claude-settings.js","lineNumber":123,"sourceCode":"      && (!isJsonObject(hook.headers)\n        || !Object.values(hook.headers).every(value => typeof value === 'string'))\n    ) {\n      throw new Error(`Invalid managed hook handler at ${label}: invalid headers`);\n    }\n    if (\n      hook.allowedEnvVars !== undefined\n      && (!Array.isArray(hook.allowedEnvVars)\n        || !hook.allowedEnvVars.every(isNonEmptyString))\n    ) {\n      throw new Error(`Invalid managed hook handler at ${label}: invalid allowedEnvVars`);\n    }\n    return;\n  }\n  if (!isNonEmptyString(hook.prompt)) {\n    throw new Error(`Invalid managed hook handler at ${label}: invalid prompt`);\n  }\n  if (hook.model !== undefined && !isNonEmptyString(hook.model)) {\n    throw new Error(`Invalid managed hook handler at ${label}: invalid model`);\n  }\n}\n\nfunction validateManagedHooks(managedHooks, label = 'managed hooks') {\n  if (!isJsonObject(managedHooks)) {\n    throw new Error(`Invalid ${label}: expected a JSON object`);\n  }\n  if (Object.keys(managedHooks).length === 0) {\n    throw new Error(`Invalid ${label}: expected at least one hook event`);\n  }\n\n  const seenIds = new Set();\n  for (const [event, entries] of Object.entries(managedHooks)) {\n    if (!VALID_EVENTS.has(event)) {\n      throw new Error(`Invalid ${label}: unsupported hook event \"${event}\"`);\n    }\n    if (!Array.isArray(entries)) {\n      throw new Error(`Invalid ${label}.${event}: expected an array`);","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install/claude-settings.js#L105-L141","documentation":"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).","triggerScenarios":"validateManagedHooks encounters {type:'prompt', prompt:'x', model:''}, model:'   ', model:3.5, model:{name:'haiku'}, or model:null.","commonSituations":"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.","solutions":["Set model to a non-empty string model id, e.g. model:'sonnet'.","Remove the model field to use the default model.","Quote model ids in YAML so they stay strings.","Ensure env-placeholder substitution for model names actually resolves."],"exampleFix":"// before\n{ \"type\": \"prompt\", \"prompt\": \"Review\", \"model\": 4.5 }\n// after\n{ \"type\": \"prompt\", \"prompt\": \"Review\", \"model\": \"sonnet\" }","handlingStrategy":"validation","validationCode":"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');","typeGuard":"const hasValidModel = (h) => h.model === undefined || (typeof h.model === 'string' && h.model.trim() !== '');","tryCatchPattern":"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; }","preventionTips":["Quote model ids in YAML.","Delete model field to accept the default.","Reject numeric model values at config-load time."],"tags":["config","validation","types"],"backgroundTag":"invalid-argument-value","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}