affaan-m/ECC · error
Invalid managed hook handler at
Error message
Invalid managed hook handler at ${label}: invalid prompt What it means
Hooks that are not of type 'command' or 'http' (i.e. prompt/agent hooks) must have a 'prompt' field that is a non-empty string. validateHookHandler throws this error when such a hook lacks prompt, has a blank prompt, or prompt is a non-string value.
Solutions
- Add a non-empty prompt string: {type:'prompt', prompt:'Review the staged diff for security issues'}.
- Rename instruction/message/text keys to prompt.
- Join any array-of-lines into a single string (e.g. lines.join('\n')).
- Check that template interpolation did not produce an empty string.
Example fix
// before
{ "type": "prompt", "instruction": "Summarize the changes" }
// after
{ "type": "prompt", "prompt": "Summarize the changes" } Defensive patterns
Strategy: validation
Validate before calling
const bad = hooks.filter(h=>h.type!=='command'&&h.type!=='http'&&!(typeof h.prompt==='string'&&h.prompt.trim()!=='')); if (bad.length) throw new Error('prompt hooks need non-empty prompt'); Type guard
const hasPrompt = (h) => ['command','http'].includes(h.type) || (typeof h.prompt === 'string' && h.prompt.trim() !== '');
Try / catch
try { installHooks(cfg); } catch (e) { if (e.message.includes('invalid prompt')) { console.error('Prompt/agent hook missing prompt text:', e.message); process.exitCode = 1; } else throw e; } Prevention
- Name the field 'prompt' (not instruction/text/message).
- Join multiline prompt arrays into one string.
- Check template substitution leaves non-empty prompt.
When it happens
Trigger: validateManagedHooks encounters {type:'prompt'} with no prompt, {type:'prompt', prompt:''}, {type:'prompt', prompt:["step1","step2"]}, or {type:'agent', agent:'reviewer'} missing prompt.
Common situations: Prompt hooks authored with the instruction text under another key (instruction, message, text); multi-line prompts stored as arrays; copying a command hook and forgetting to add prompt; empty prompt after template variable substitution.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Invalid hook entry at
- Invalid hooks config: expected a JSON object with a hooks…
- Invalid . : expected a non-empty hook array
- Invalid : expected at least one hook event
- Invalid managed hook handler at
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/198282ecbaeca829.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install/claude-settings.js:120
}
if (
hook.headers !== undefined
&& (!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}"`);View on GitHub (pinned to 8321021c54)