{"record":{"id":"e215388ec657908b","repo":"affaan-m/ECC","slug":"invalid-hook-entry-at-label-event-index","errorCode":null,"errorMessage":"Invalid hook entry at ${label}.${event}[${index}]","messagePattern":"Invalid hook entry at (.+?)\\.(.+?)\\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install/claude-settings.js","lineNumber":205,"sourceCode":"      });\n    });\n  }\n\n  return cloneValue(managedHooks);\n}\n\nfunction validateRecordedManagedHooks(managedHooks, label = 'recorded managed hooks') {\n  if (!isJsonObject(managedHooks) || Object.keys(managedHooks).length === 0) {\n    throw new Error(`Invalid ${label}: expected a non-empty JSON object`);\n  }\n  for (const [event, entries] of Object.entries(managedHooks)) {\n    if (!isNonEmptyString(event) || !Array.isArray(entries) || entries.length === 0) {\n      throw new Error(`Invalid ${label}.${event}: expected a non-empty hook array`);\n    }\n    const seenIds = new Set();\n    entries.forEach((entry, index) => {\n      if (!isJsonObject(entry) || !isNonEmptyString(entry.id) || !Array.isArray(entry.hooks)) {\n        throw new Error(`Invalid hook entry at ${label}.${event}[${index}]`);\n      }\n      if (seenIds.has(entry.id)) {\n        throw new Error(\n          `Invalid ${label}: expected unique id \"${entry.id}\" within event \"${event}\"`\n        );\n      }\n      seenIds.add(entry.id);\n    });\n  }\n  return cloneValue(managedHooks);\n}\n\nfunction validateSettings(settings, label = 'Claude settings') {\n  if (!isJsonObject(settings)) {\n    throw new Error(`Invalid ${label}: expected a JSON object`);\n  }\n\n  if (Object.prototype.hasOwnProperty.call(settings, 'hooks')) {","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install/claude-settings.js#L187-L223","documentation":"Each entry inside a hook event array must be a JSON object with a non-empty string \"id\" and an array \"hooks\". The validator walks every entry by index and throws this error at the first entry violating that shape. It guarantees recorded hook entries can be safely merged into settings without undefined fields downstream.","triggerScenarios":"Calling validateRecordedManagedHooks (or validate/previousHooks/recordedHooks) where managedHooks[event][index] is not an object, has a missing/empty/non-string id, or has a missing or non-array hooks field.","commonSituations":"Hand-edited hooks.json entries where \"id\" was renamed or removed, YAML-to-JSON conversion dropped fields, or a script appended a bare hook command object instead of the wrapper { id, hooks } structure.","solutions":["Open the recorded hooks data and fix the entry at the reported index so it has a non-empty string id and an array hooks field","Wrap bare hook commands in the expected { id, hooks: [...] } shape","Regenerate the recording from the canonical hooks.json","Add a pre-validation pass on your own data to reject entries lacking id/hooks before calling the library"],"exampleFix":"// before\n{ \"hooks\": { \"type\": \"command\", \"command\": \"node hook.js\" } }\n// after\n{ \"id\": \"format-on-edit\", \"hooks\": [ { \"type\": \"command\", \"command\": \"node hook.js\" } ] }","handlingStrategy":"validation","validationCode":"const validEntry = (e) => e && typeof e === 'object' && typeof e.id === 'string' && e.id.length > 0 && Array.isArray(e.hooks);","typeGuard":"const isHookEntry = (v) => typeof v === 'object' && v !== null && typeof v.id === 'string' && Array.isArray(v.hooks);","tryCatchPattern":"try { validateRecordedManagedHooks(hooks); } catch (e) { const m = /hook entry at (.+)\\[(\\d+)\\]/.exec(e.message); if (m) { console.error('Bad entry:', m[1], 'index', m[2]); } throw e; }","preventionTips":["Always wrap hook commands in { id, hooks: [...] }","Use a JSON schema validator on hooks.json before install","Copy entry blocks wholesale, then change id — never delete fields","Add unit tests for the recording serializer"],"tags":["validation","hooks","config"],"backgroundTag":"schema-validation-failed","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"}