affaan-m/ECC · error
Invalid managed hook handler at
Error message
Invalid managed hook handler at ${label}: invalid async flag What it means
For command-type hooks, the optional 'async' flag must be a boolean. validateHookHandler throws this error when hook.async is present on a {type:'command'} handler but is not true or false (e.g. a string "true", a number, or null).
Solutions
- Change the async value to a real JSON boolean: true or false.
- Remove the async field entirely if you do not need it (undefined is accepted).
- Fix your config generator to emit booleans, not strings (JSON.stringify the value, don't String() it).
- Re-validate the settings object before writing it.
Example fix
// before
{ "type": "command", "command": "npm test", "async": "true" }
// after
{ "type": "command", "command": "npm test", "async": true } Defensive patterns
Strategy: validation
Validate before calling
const bad = hooks.filter(h=>h.type==='command'&&h.async!==undefined&&typeof h.async!=='boolean'); if (bad.length) throw new Error('async must be boolean on: '+bad.map(JSON.stringify)); Type guard
const hasValidAsync = (h) => h.async === undefined || typeof h.async === 'boolean';
Try / catch
try { installHooks(cfg); } catch (e) { if (e.message.includes('invalid async flag')) { e.message += ' — check that async is a literal true/false, not a quoted string'; throw e; } throw e; } Prevention
- Write booleans unquoted in JSON/YAML configs.
- Round-trip configs through JSON.parse to catch stringified booleans.
- Template generators should emit typeof-checked values.
When it happens
Trigger: validateManagedHooks encounters a command handler like {type:'command', command:'x', async:'true'} or async:1 or async:null.
Common situations: Hand-editing settings.json and quoting the boolean ('async': "true"); generating hooks from a template engine that stringifies booleans; copying config from docs where async appeared as a YAML unquoted true that got serialized as a string.
Related errors
- Invalid : expected a JSON object
- Invalid managed hook handler at
- Invalid managed hook handler at
- application config exceeds local size limit
- Asset request_id/modality does not match the bundle
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/33cf97ec174d2a53.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install/claude-settings.js:91
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`);
}
return;
}
if (hook.async !== undefined) {
throw new Error(`Invalid managed hook handler at ${label}: async requires command type`);
}
if (hook.type === 'http') {
if (!isNonEmptyString(hook.url)) {
throw new Error(`Invalid managed hook handler at ${label}: invalid url`);
}
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`);
}View on GitHub (pinned to 8321021c54)