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 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.
Source
Thrown at scripts/lib/install-executor.js:202
sourceRelativePath: options.sourceRelativePath,
destinationPath: options.destinationPath,
strategy: options.strategy || 'preserve-relative-path'
})
);
return true;
}
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 addCursorAgentDataScaffoldOperations(operations, options) {
const scaffoldRoot = path.join(options.sourceRoot, 'scaffolds', 'cursor');
if (!fs.existsSync(scaffoldRoot)) {
return;
}
addFileCopyOperation(operations, {
moduleId: options.moduleId,
sourceRoot: options.sourceRoot,
sourceRelativePath: path.join('scaffolds', 'cursor', 'ecc-agent-data.json'),
destinationPath: path.join(options.targetRoot, 'ecc-agent-data.json'),
strategy: 'preserve-relative-path'
});View on GitHub (pinned to 01e15490f0)
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.
Example fix
// before (manifests/install-components.json)
[
{ "id": "x" },
{ "id": "y" }
]
// after
{
"components": [
{ "id": "x" },
{ "id": "y" }
]
} 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(filePath, 'utf8'));
if (!isPlainObject(parsed)) {
throw new Error(`${label} at ${filePath} must be a JSON object`);
} Type guard
function isJsonObject(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v);
} Try / catch
try {
return readJsonObject(filePath, label);
} catch (err) {
if (/expected a JSON object/.test(err.message)) {
throw new Error(`${label} schema wrong: top level must be { ... }`);
}
throw err;
} Prevention
- 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.
When it happens
Trigger: 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: [...] }.
Common situations: 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.
Related errors
- Failed to parse ${label} at ${filePath}: ${error.message}
- Failed to read ${label}: ${error.message}
- Install module ${moduleId} has invalid targets; expected an
- ${source} is missing the catalog count description
- Invalid JSON in ${label}: ${error.message}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/91ddf37dfa22351f.
Report an issue: GitHub.