{"record":{"id":"fb375e6905ba4687","repo":"affaan-m/ECC","slug":"invalid-hooks-config-at-hookssourcepath-expect","errorCode":null,"errorMessage":"Invalid hooks config at ${hooksSourcePath}: expected \"hooks\" to be a JSON object","messagePattern":"Invalid hooks config at (.+?): expected \"hooks\" to be a JSON object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/install/apply.js","lineNumber":309,"sourceCode":"  if (!plan.adapter || (plan.adapter.target !== 'claude' && plan.adapter.target !== 'claude-project')) {\n    return null;\n  }\n\n  const pluginRoot = plan.targetRoot;\n  const hooksDestinationPath = path.join(plan.targetRoot, 'hooks', 'hooks.json');\n  const hooksOperation = findHooksOperation(plan, hooksDestinationPath);\n  if (!hooksOperation) {\n    return null;\n  }\n  const hooksSourcePath = hooksOperation.sourcePath;\n  if (!fs.existsSync(hooksSourcePath)) {\n    return null;\n  }\n\n  const hooksConfig = readJsonObject(hooksSourcePath, 'hooks config');\n  const resolvedHooks = replacePluginRootPlaceholders(hooksConfig.hooks, pluginRoot);\n  if (!resolvedHooks || typeof resolvedHooks !== 'object' || Array.isArray(resolvedHooks)) {\n    throw new Error(`Invalid hooks config at ${hooksSourcePath}: expected \"hooks\" to be a JSON object`);\n  }\n\n  return {\n    hooksOperation,\n    hooksDestinationPath,\n    resolvedHooksConfig: {\n      ...hooksConfig,\n      hooks: resolvedHooks,\n    },\n  };\n}\n\nfunction previewInstallPlan(plan) {\n  const migration = prepareClaudeSkillMigration(plan);\n  return {\n    ...plan,\n    statePreview: migration.finalState,\n    plannedOperations: [...plan.operations],","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/affaan-m/ECC/blob/06c5e118c4d3e6c3b7f9445f973a2194c82de193/scripts/lib/install/apply.js#L291-L327","documentation":"The hooks.json staged for a Claude/Claude-project install parsed to a JSON object, but its 'hooks' member is not itself a JSON object. The hooks rewriter needs the hooks key to be a mapping keyed by event name to substitute plugin-root placeholders.","triggerScenarios":"Thrown at scripts/lib/install/apply.js:309 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Edit the hooks config so the top-level \"hooks\" key is a JSON object.","Restore hooks.json from the repository if it was hand-edited incorrectly."],"exampleFix":"node -e \"const c=require('<hooksSourcePath>'); if(typeof c.hooks!=='object') throw new Error('fix hooks')\"","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"06c5e118c4d3e6c3b7f9445f973a2194c82de193","analyzedAt":"2026-08-18T11:27:13.915Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}