{"record":{"id":"91ddf37dfa22351f","repo":"affaan-m/ECC","slug":"invalid-label-at-filepath-expected-a-json-o","errorCode":null,"errorMessage":"Invalid ${label} at ${filePath}: expected a JSON object","messagePattern":"Invalid (.+?) at (.+?): expected a JSON object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/install-executor.js","lineNumber":202,"sourceCode":"      sourceRelativePath: options.sourceRelativePath,\n      destinationPath: options.destinationPath,\n      strategy: options.strategy || 'preserve-relative-path'\n    })\n  );\n\n  return true;\n}\n\nfunction readJsonObject(filePath, label) {\n  let parsed;\n  try {\n    parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));\n  } catch (error) {\n    throw new Error(`Failed to parse ${label} at ${filePath}: ${error.message}`);\n  }\n\n  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n    throw new Error(`Invalid ${label} at ${filePath}: expected a JSON object`);\n  }\n\n  return parsed;\n}\n\nfunction addCursorAgentDataScaffoldOperations(operations, options) {\n  const scaffoldRoot = path.join(options.sourceRoot, 'scaffolds', 'cursor');\n  if (!fs.existsSync(scaffoldRoot)) {\n    return;\n  }\n\n  addFileCopyOperation(operations, {\n    moduleId: options.moduleId,\n    sourceRoot: options.sourceRoot,\n    sourceRelativePath: path.join('scaffolds', 'cursor', 'ecc-agent-data.json'),\n    destinationPath: path.join(options.targetRoot, 'ecc-agent-data.json'),\n    strategy: 'preserve-relative-path'\n  });","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/install-executor.js#L184-L220","documentation":"Thrown by readJsonObject() after the file parsed successfully but the resulting value is not a plain object (it is null, an array, a primitive, or non-object). The label and path pinpoint which artifact has the wrong top-level shape.","triggerScenarios":"readJsonObject(filePath, label) where parsed is an array [...] or primitive. Typical when a manifest file is accidentally an array of entries instead of { modules: [...] } / { components: [...] }.","commonSituations":"Tool emits the wrong top-level structure (array vs object); manual edit replaced the wrapper object with a bare list; a scaffold data file was rewritten as a list of records.","solutions":["Open the file and confirm the top level is an object literal { ... }.","If the contents are an array, wrap them: { \"entries\": [...] } or restore the expected schema key.","Cross-check the schema against a known-good sibling manifest in the same directory."],"exampleFix":"// before (manifests/install-components.json)\n[\n  { \"id\": \"x\" },\n  { \"id\": \"y\" }\n]\n\n// after\n{\n  \"components\": [\n    { \"id\": \"x\" },\n    { \"id\": \"y\" }\n  ]\n}","handlingStrategy":"validation","validationCode":"function isPlainObject(v) { return Boolean(v) && typeof v === 'object' && !Array.isArray(v); }\nconst parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));\nif (!isPlainObject(parsed)) {\n  throw new Error(`${label} at ${filePath} must be a JSON object`);\n}","typeGuard":"function isJsonObject(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  return readJsonObject(filePath, label);\n} catch (err) {\n  if (/expected a JSON object/.test(err.message)) {\n    throw new Error(`${label} schema wrong: top level must be { ... }`);\n  }\n  throw err;\n}","preventionTips":["Ship JSON Schemas for each manifest and validate in CI.","Generate manifests with code rather than hand-editing.","Add tests that assert the top-level shape of every shipped manifest."],"tags":["json","schema","install","manifest"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}