affaan-m/ECC · error · Error
Policy file ${resolvedPath} must contain a JSON object, got
Error message
Policy file ${resolvedPath} must contain a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed} What it means
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.
Source
Thrown at scripts/lib/github-coordination/policy.js:69
const resolvedPath = configPath
? path.resolve(configPath)
: path.join(rootDir, 'config', DEFAULT_CONFIG_FILE);
if (!fs.existsSync(resolvedPath)) {
return {
...DEFAULT_POLICY,
sourcePath: null,
};
}
let parsed;
try {
parsed = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
} catch (error) {
throw new Error(`Failed to load policy from ${resolvedPath}: ${error.message}`);
}
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error(`Policy file ${resolvedPath} must contain a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed}`);
}
const labels = typeof parsed.labels === 'object' && parsed.labels !== null && !Array.isArray(parsed.labels) ? parsed.labels : {};
const review = typeof parsed.review === 'object' && parsed.review !== null && !Array.isArray(parsed.review) ? parsed.review : {};
const validation = typeof parsed.validation === 'object' && parsed.validation !== null && !Array.isArray(parsed.validation) ? parsed.validation : {};
const branchModel = typeof parsed.branchModel === 'object' && parsed.branchModel !== null && !Array.isArray(parsed.branchModel) ? parsed.branchModel : {};
const project = typeof parsed.project === 'object' && parsed.project !== null && !Array.isArray(parsed.project) ? parsed.project : {};
const fieldNames = typeof project.fieldNames === 'object' && project.fieldNames !== null && !Array.isArray(project.fieldNames) ? project.fieldNames : {};
return {
...DEFAULT_POLICY,
...parsed,
labels: { ...DEFAULT_LABELS, ...labels },
review: { ...DEFAULT_POLICY.review, ...review },
validation: { ...DEFAULT_POLICY.validation, ...validation },
branchModel: { ...DEFAULT_POLICY.branchModel, ...branchModel },
project: {
...DEFAULT_POLICY.project,
...project,
fieldNames: { ...DEFAULT_POLICY.project.fieldNames, ...fieldNames },View on GitHub (pinned to 01e15490f0)
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')".
Example fix
// before (file contents):
["epic", "coordination:available"]
// after:
{
"labels": {
"epic": "epic",
"available": "coordination:available"
}
} Defensive patterns
Strategy: validation
Validate before calling
function isPlainObject(v) { return Boolean(v) && typeof v === 'object' && !Array.isArray(v); }
const parsed = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
if (!isPlainObject(parsed)) {
throw new Error(`Policy at ${resolvedPath} must be a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed}`);
} Type guard
function isPolicyObject(v) {
if (!v || typeof v !== 'object' || Array.isArray(v)) return false;
return true;
} Try / catch
try {
return loadPolicy(rootDir);
} catch (err) {
if (/must contain a JSON object/) {
// surface a friendlier error pointing at the offending file
throw new Error(`Policy shape invalid: ${err.message}`);
}
throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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: [...] }.
Related errors
- Failed to load policy from ${resolvedPath}: ${error.message}
- MCP config must include an mcpServers object
- ${source} is missing the catalog count description
- Invalid JSON in ${label}: ${error.message}
- invalid repo: expected non-empty string, got ${JSON.stringif
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/bbe3e0dd1c646d88.
Report an issue: GitHub.