affaan-m/ECC · error
Invalid at : expected a JSON object
Error message
Invalid ${label} at ${filePath}: expected a JSON object What it means
readJsonObject in the Kimi project target requires the parsed JSON root to be a plain object; null, arrays, and primitives are rejected because MCP merge needs an object to merge `mcpServers` into. The message includes the labeled file path so the offending file is easy to find.
Solutions
- Open the file at filePath and change the top-level value to a JSON object
- If the file holds an array of servers, wrap it: `{ "mcpServers": { ... } }` mapping names to server objects
- Replace `null`/`[]` placeholders with `{}` and re-run the install
Example fix
// before
[ { "name": "context7", "command": "npx" } ]
// after
{ "mcpServers": { "context7": { "command": "npx" } } } Defensive patterns
Strategy: type-guard
Validate before calling
// Pre-check root shape of the Kimi MCP config
const parsed = JSON.parse(fs.readFileSync(kimiMcpPath, 'utf8'));
if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
console.error(`${kimiMcpPath} must be a JSON object at the top level`);
} Type guard
function isJsonObject(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v);
} Try / catch
try {
runInstallOperation(op);
} catch (e) {
if (/Invalid .* at .*: expected a JSON object/.test(e.message)) {
// convert the file root to an object and re-run the install
} else throw e;
} Prevention
- Structure MCP configs as `{ "mcpServers": { ... } }` objects, never arrays
- Use `{}` for empty config files instead of `[]` or `null`
- Validate parsed config root shape with a type guard before merge operations
When it happens
Trigger: createMcpMergeOperation reads a Kimi project config file whose contents are valid JSON but whose top-level value is an array (e.g. `[]`), `null`, a string, or a number.
Common situations: A user initialized the Kimi MCP config as a JSON array of servers instead of an object; a template or script wrote `null` as a placeholder; an export tool produced a list-shaped config.
Related errors
- Failed to parse at
- Invalid at : expected a JSON object
- Failed to parse at
- Invalid at : expected a JSON object
- Invalid at : expected a JSON object
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/b19cb379b99c1be4.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install-targets/kimi-project.js:19
const fs = require('fs');
const path = require('path');
const {
createInstallTargetAdapter,
createManagedOperation,
isForeignPlatformPath,
} = require('./helpers');
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 createMcpMergeOperation(moduleId, repoRoot, targetRoot) {
if (!repoRoot) {
throw new Error('repoRoot is required to plan Kimi MCP configuration');
}
const sourceRelativePath = '.mcp.json';
const sourcePath = path.join(repoRoot, sourceRelativePath);
if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {
return null;
}
return createManagedOperation({
kind: 'merge-json',View on GitHub (pinned to 8321021c54)