affaan-m/ECC · error · Error
Invalid ${label} at ${filePath}: expected a JSON object
Error message
Invalid ${label} at ${filePath}: expected a JSON object What it means
Thrown by readJsonObject() after JSON.parse succeeded but the parsed value is not a plain object — it is an array, a primitive (string/number/boolean), or null. The merge-json strategy requires a JSON object root; anything else cannot be merged into the destination.
Source
Thrown at scripts/lib/install-targets/cursor-project.js:32
if (path.basename(sourceRelativeFile).toLowerCase() === 'readme.md') {
return null;
}
return fileName.endsWith('.md')
? `${fileName.slice(0, -3)}.mdc`
: fileName;
}
function readJsonObject(filePath, label) {
let parsed;
try {
parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch (error) {
throw new Error(`Failed to parse ${label} at ${filePath}: ${error.message}`);
}
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new Error(`Invalid ${label} at ${filePath}: expected a JSON object`);
}
return parsed;
}
function createJsonMergeOperation({ moduleId, repoRoot, sourceRelativePath, destinationPath }) {
const sourcePath = path.join(repoRoot, sourceRelativePath);
if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {
return null;
}
return createManagedOperation({
kind: 'merge-json',
moduleId,
sourceRelativePath,
destinationPath,
strategy: 'merge-json',
ownership: 'managed',View on GitHub (pinned to 01e15490f0)
Solutions
- Ensure the source file's top-level value is an object ({...}).
- If the data is naturally an array, change the operation strategy from merge-json to flat-file copy.
- Wrap the array under a key: { "items": [...] }.
- Point the operation at a different source file that contains an object.
Example fix
// before — source file is an array
[ "a", "b" ]
// after — wrap in an object (if a merge is intended)
{ "allowed": ["a", "b"] } Defensive patterns
Strategy: type-guard
Validate before calling
const value = JSON.parse(fs.readFileSync(filePath, 'utf8'));
if (!value || typeof value !== 'object' || Array.isArray(value)) {
throw new Error(`${filePath} must contain a JSON object, got ${Array.isArray(value) ? 'array' : typeof value}`);
} Type guard
/** @param {unknown} v */
function isPlainObject(v) {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Prevention
- Author merge sources as objects — wrap arrays under a key.
- If a source is naturally an array, use a flat-file copy operation, not merge-json.
When it happens
Trigger: A source file contains a JSON array ([...]) or a single primitive (e.g. "true") and is referenced by a merge-json operation. Also a file that contains only null.
Common situations: A list-style JSON (e.g. a list of allowed tools) was mistakenly referenced as a merge source; an empty file parsed to undefined; the wrong file was wired into the module's paths.
Related errors
- Failed to parse ${label} at ${filePath}: ${error.message}
- Invalid ${label}: expected JSON-compatible data
- ECC_PROJECT_DIR must be a child path within /workspace.
- Unknown argument: ${arg}
- --json may only be provided once
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/3dce563a1ccb6498.
Report an issue: GitHub.