{"record":{"id":"0e36834739303a99","repo":"affaan-m/ECC","slug":"invalid-managed-hook-handler-at-label-async-requires-command","errorCode":null,"errorMessage":"Invalid managed hook handler at ${label}: async requires command type","messagePattern":"Invalid managed hook handler at (.+?): async requires command type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install/claude-settings.js","lineNumber":97,"sourceCode":"    throw new Error(`Invalid managed hook handler at ${label}: invalid timeout`);\n  }\n\n  if (hook.type === 'command') {\n    const validCommand = isNonEmptyString(hook.command)\n      || (Array.isArray(hook.command)\n        && hook.command.length > 0\n        && hook.command.every(isNonEmptyString));\n    if (!validCommand) {\n      throw new Error(`Invalid managed hook handler at ${label}: invalid command`);\n    }\n    if (hook.async !== undefined && typeof hook.async !== 'boolean') {\n      throw new Error(`Invalid managed hook handler at ${label}: invalid async flag`);\n    }\n    return;\n  }\n\n  if (hook.async !== undefined) {\n    throw new Error(`Invalid managed hook handler at ${label}: async requires command type`);\n  }\n  if (hook.type === 'http') {\n    if (!isNonEmptyString(hook.url)) {\n      throw new Error(`Invalid managed hook handler at ${label}: invalid url`);\n    }\n    if (\n      hook.headers !== undefined\n      && (!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`);","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install/claude-settings.js#L79-L115","documentation":"The 'async' flag is only meaningful for hooks of type 'command'. validateHookHandler throws this error when a hook of any other type (http, prompt, agent) defines hook.async. Remove async or switch the hook to type 'command'.","triggerScenarios":"validateManagedHooks encounters {type:'http', url:'...', async:true}, {type:'prompt', prompt:'...', async:false}, or any non-command handler carrying an async key.","commonSituations":"Copying the async property from a command hook when converting it to an http/prompt hook; a shared hook template that always injects async; schema drift after the library tightened validation in a newer version.","solutions":["Delete the async property from non-command hook handlers.","If the hook genuinely needs async semantics, change its type to 'command' and supply a valid command field.","Update any shared templates or generators so async is only emitted for command-type hooks.","Re-run validation after the edit to surface any remaining handler errors."],"exampleFix":"// before\n{ \"type\": \"prompt\", \"prompt\": \"Review the diff\", \"async\": true }\n// after\n{ \"type\": \"prompt\", \"prompt\": \"Review the diff\" }","handlingStrategy":"validation","validationCode":"const bad = hooks.filter(h=>h.type!=='command'&&'async' in h); if (bad.length) throw new Error('async only allowed on command hooks');","typeGuard":"const asyncAllowed = (h) => h.type === 'command' || h.async === undefined;","tryCatchPattern":"try { installHooks(cfg); } catch (e) { if (e.message.includes('async requires command type')) { console.error('Remove async from non-command hook:', e.message); process.exitCode = 1; } else throw e; }","preventionTips":["Only emit async in command-hook templates.","Strip unknown fields when converting hooks between types.","Document type-specific fields per hook type."],"tags":["config","validation","hooks"],"backgroundTag":"conflicting-config-options","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"}