{"record":{"id":"bbe3e0dd1c646d88","repo":"affaan-m/ECC","slug":"policy-file-resolvedpath-must-contain-a-json-ob","errorCode":null,"errorMessage":"Policy file ${resolvedPath} must contain a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed}","messagePattern":"Policy file (.+?) must contain a JSON object, got (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/github-coordination/policy.js","lineNumber":69,"sourceCode":"  const resolvedPath = configPath\n    ? path.resolve(configPath)\n    : path.join(rootDir, 'config', DEFAULT_CONFIG_FILE);\n\n  if (!fs.existsSync(resolvedPath)) {\n    return {\n      ...DEFAULT_POLICY,\n      sourcePath: null,\n    };\n  }\n\n  let parsed;\n  try {\n    parsed = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));\n  } catch (error) {\n    throw new Error(`Failed to load policy from ${resolvedPath}: ${error.message}`);\n  }\n  if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n    throw new Error(`Policy file ${resolvedPath} must contain a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed}`);\n  }\n  const labels = typeof parsed.labels === 'object' && parsed.labels !== null && !Array.isArray(parsed.labels) ? parsed.labels : {};\n  const review = typeof parsed.review === 'object' && parsed.review !== null && !Array.isArray(parsed.review) ? parsed.review : {};\n  const validation = typeof parsed.validation === 'object' && parsed.validation !== null && !Array.isArray(parsed.validation) ? parsed.validation : {};\n  const branchModel = typeof parsed.branchModel === 'object' && parsed.branchModel !== null && !Array.isArray(parsed.branchModel) ? parsed.branchModel : {};\n  const project = typeof parsed.project === 'object' && parsed.project !== null && !Array.isArray(parsed.project) ? parsed.project : {};\n  const fieldNames = typeof project.fieldNames === 'object' && project.fieldNames !== null && !Array.isArray(project.fieldNames) ? project.fieldNames : {};\n  return {\n    ...DEFAULT_POLICY,\n    ...parsed,\n    labels: { ...DEFAULT_LABELS, ...labels },\n    review: { ...DEFAULT_POLICY.review, ...review },\n    validation: { ...DEFAULT_POLICY.validation, ...validation },\n    branchModel: { ...DEFAULT_POLICY.branchModel, ...branchModel },\n    project: {\n      ...DEFAULT_POLICY.project,\n      ...project,\n      fieldNames: { ...DEFAULT_POLICY.project.fieldNames, ...fieldNames },","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/github-coordination/policy.js#L51-L87","documentation":"Thrown by loadPolicy() after the policy file parses successfully but the top-level JSON value is not an object (it is an array, string, number, boolean, or null). The policy must be a JSON object so its fields (labels, review, validation, branchModel, project) can be merged over DEFAULT_POLICY.","triggerScenarios":"loadPolicy reads a file whose contents are a bare JSON array [...] or a primitive (e.g. \"\" or 42 or true); the typeof/Array.isArray check at policy.js:68 fails and the message reports 'array' or the actual typeof.","commonSituations":"A user pastes a list of label overrides as the entire file instead of an object; a tool writes a top-level array; file was auto-generated by a script that serializes an array instead of { labels: [...] }.","solutions":["Wrap the contents in an object: { ...your current JSON... }.","If the file holds a labels array, move it under the labels key as an object map, e.g. { \"labels\": { \"epic\": \"epic\" } }.","Re-validate with: node -e \"const v=JSON.parse(require('fs').readFileSync('config/github-native-coordination.json','utf8')); if(typeof v!=='object'||v===null||Array.isArray(v)) throw new Error('top level must be object')\"."],"exampleFix":"// before (file contents):\n[\"epic\", \"coordination:available\"]\n// after:\n{\n  \"labels\": {\n    \"epic\": \"epic\",\n    \"available\": \"coordination:available\"\n  }\n}","handlingStrategy":"validation","validationCode":"function isPlainObject(v) { return Boolean(v) && typeof v === 'object' && !Array.isArray(v); }\nconst parsed = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));\nif (!isPlainObject(parsed)) {\n  throw new Error(`Policy at ${resolvedPath} must be a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed}`);\n}","typeGuard":"function isPolicyObject(v) {\n  if (!v || typeof v !== 'object' || Array.isArray(v)) return false;\n  return true;\n}","tryCatchPattern":"try {\n  return loadPolicy(rootDir);\n} catch (err) {\n  if (/must contain a JSON object/) {\n    // surface a friendlier error pointing at the offending file\n    throw new Error(`Policy shape invalid: ${err.message}`);\n  }\n  throw err;\n}","preventionTips":["Provide a JSON Schema for the policy and validate in CI.","Document an example policy file in the project README.","Add a unit test that loadPolicy rejects an array-shaped file."],"tags":["config","json","schema","github-coordination"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}