affaan-m/ECC · error
Invalid managed hook handler at
Error message
Invalid managed hook handler at ${label}: expected a JSON object What it means
validateHookHandler checks each managed hook handler against the expected Claude hook-handler schema. A handler that is not a JSON object (string, array, number, null) fails the very first check. The label in the message identifies where in the hooks structure the bad value sits.
Solutions
- Rewrite the handler at the labeled location as a JSON object with a valid 'type' field.
- Validate the settings JSON structure (jq or a schema check) before running the install.
- Let the ECC installer generate hook entries instead of hand-authoring them.
Example fix
// before
"hooks": { "PreToolUse": ["node my-hook.js"] }
// after
"hooks": { "PreToolUse": [{ "type": "command", "command": "node my-hook.js" }] } Defensive patterns
Strategy: validation
Validate before calling
const isHookHandlerObject = (h) => typeof h === 'object' && h !== null && !Array.isArray(h);
for (const handlers of Object.values(settings.hooks ?? {})) {
for (const h of handlers) if (!isHookHandlerObject(h)) throw new Error('hook handler must be an object');
} Type guard
const isJsonObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
Try / catch
try {
validateManagedHooks(hooks);
} catch (e) {
if (e.message.includes('expected a JSON object')) {
console.error('Fix the hook handler shape at:', e.message.match(/at (.+?):/)?.[1]);
} else throw e;
} Prevention
- Author hooks as objects: { type, command, timeout? } — never bare strings.
- Run jq or a JSON schema check on settings.json before installing.
- Let ECC scripts generate hook entries rather than hand-writing them.
When it happens
Trigger: validateManagedHooks encounters a hook handler value that is not a plain object — e.g. a hook entry defined as a string command instead of an object with type/command fields.
Common situations: Hand-written settings.json where a hook was written as "node hook.js" instead of {"type":"command","command":"node hook.js"}; JSON produced by another tool using a different hook schema.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid managed hook handler at
- Invalid managed hook handler at
- -32602
- application request must be a JSON object
- artifact path must be a non-empty relative path
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/4d798eb9776dc487.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install/claude-settings.js:73
return path.join(targetRoot, CLAUDE_SETTINGS_FILENAME);
}
function assertClaudeSettingsPath(destinationPath, trustedRoot) {
const resolvedDestination = path.resolve(destinationPath);
const resolvedExpected = path.resolve(getClaudeSettingsPath(trustedRoot));
const pathsMatch = process.platform === 'win32'
? resolvedDestination.toLowerCase() === resolvedExpected.toLowerCase()
: resolvedDestination === resolvedExpected;
if (!pathsMatch) {
throw new Error(
`Refusing to manage Claude hooks outside the canonical settings file: ${destinationPath}`
);
}
}
function validateHookHandler(hook, label) {
if (!isJsonObject(hook)) {
throw new Error(`Invalid managed hook handler at ${label}: expected a JSON object`);
}
if (!VALID_HOOK_TYPES.has(hook.type)) {
throw new Error(`Invalid managed hook handler at ${label}: unsupported type`);
}
if (hook.timeout !== undefined && (typeof hook.timeout !== 'number' || hook.timeout < 0)) {
throw new Error(`Invalid managed hook handler at ${label}: invalid timeout`);
}
if (hook.type === 'command') {
const validCommand = isNonEmptyString(hook.command)
|| (Array.isArray(hook.command)
&& hook.command.length > 0
&& hook.command.every(isNonEmptyString));
if (!validCommand) {
throw new Error(`Invalid managed hook handler at ${label}: invalid command`);
}
if (hook.async !== undefined && typeof hook.async !== 'boolean') {
throw new Error(`Invalid managed hook handler at ${label}: invalid async flag`);View on GitHub (pinned to 8321021c54)