{"record":{"id":"b022b0bfae05e62b","repo":"affaan-m/ECC","slug":"invalid-managed-hook-handler-at-label-invalid-url","errorCode":null,"errorMessage":"Invalid managed hook handler at ${label}: invalid url","messagePattern":"Invalid managed hook handler at (.+?): invalid url","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install/claude-settings.js","lineNumber":101,"sourceCode":"    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`);\n    }\n    return;\n  }\n  if (!isNonEmptyString(hook.prompt)) {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install/claude-settings.js#L83-L119","documentation":"For hooks of type 'http', the 'url' field is required and must be a non-empty string. validateHookHandler throws this error when an http hook lacks url, has an empty/blank url, or url is some other type (number, object, array).","triggerScenarios":"validateManagedHooks encounters {type:'http'} with no url, {type:'http', url:''}, or {type:'http', url:{host:'api.example.com'}}.","commonSituations":"Hand-written http hook where the url key was omitted or misspelled (endpoint, uri, target); environment-specific URL templating that resolved to an empty string; migrating a webhook entry between config formats.","solutions":["Add a non-empty https/http URL string to the hook, e.g. {type:'http', url:'https://api.example.com/hooks/ecc'}.","Fix misspelled keys (url, not uri/endpoint/target).","Ensure env-based URL templating actually resolves — blank after substitution still fails.","Validate the object before writing settings."],"exampleFix":"// before\n{ \"type\": \"http\", \"endpoint\": \"https://hooks.example.com/ecc\" }\n// after\n{ \"type\": \"http\", \"url\": \"https://hooks.example.com/ecc\" }","handlingStrategy":"validation","validationCode":"const bad = hooks.filter(h=>h.type==='http' && !(typeof h.url==='string' && h.url.trim()!=='')); if (bad.length) throw new Error('http hooks need non-empty url');","typeGuard":"const hasUrl = (h) => h.type !== 'http' || (typeof h.url === 'string' && h.url.trim() !== '');","tryCatchPattern":"try { installHooks(cfg); } catch (e) { if (e.message.includes('invalid url')) { console.error('HTTP hook missing url:', e.message); process.exitCode = 1; } else throw e; }","preventionTips":["Always set url on http hooks; verify env-templated URLs resolve.","Use key name exactly 'url'.","Validate with new URL(h.url) additionally to catch malformed values."],"tags":["config","validation","url"],"backgroundTag":"missing-required-config-field","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"}