affaan-m/ECC · error · Error

Failed to parse ${label} at ${filePath}: ${error.message}

Error message

Failed to parse ${label} at ${filePath}: ${error.message}

What it means

Thrown by readJsonObject in scripts/lib/install-targets/kimi-project.js when JSON.parse fails on the file at filePath. In the Kimi adapter this is called on <repoRoot>/.mcp.json (label is the sourceRelativePath '.mcp.json') inside createMcpMergeOperation, which runs during planOperations whenever a module exposes the 'mcp-configs' path. The original parse error message is inlined so the caller sees the exact JSON syntax problem.

Source

Thrown at scripts/lib/install-targets/kimi-project.js:15

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;

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Open the file at filePath (the message includes the absolute path) and run node -e "JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'))" <filePath> to surface the exact position.
  2. Fix the JSON syntax error (most commonly a trailing comma, missing quote, or single quotes instead of double).
  3. Strip a leading BOM: sed -i '1s/^\xEF\xBB\xBF//' <filePath>.
  4. Validate with jq empty <filePath> or npx jsonlint <filePath> before retrying the install.

Example fix

// before (<repoRoot>/.mcp.json)
{
  "mcpServers": {
    "context7": { "command": "npx", },
  }
}

// after
{
  "mcpServers": {
    "context7": { "command": "npx" }
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

function preflightJsonObject(filePath) {
  const raw = require('fs').readFileSync(filePath, 'utf8').replace(/^\uFEFF/, '');
  const v = JSON.parse(raw); // throws on bad JSON
  if (!v || typeof v !== 'object' || Array.isArray(v)) {
    throw new Error(`${filePath} top level must be a JSON object`);
  }
  return v;
}
// before planning the Kimi install:
const mcpPath = path.join(repoRoot, '.mcp.json');
if (fs.existsSync(mcpPath)) preflightJsonObject(mcpPath);

Type guard

function isJsonObject(value) {
  return value !== null && typeof value === 'object' && !Array.isArray(value);
}

Try / catch

try {
  planInstallTargetScaffold({ target: 'kimi', modules, repoRoot, projectRoot });
} catch (err) {
  if (/Failed to parse .*\.mcp\.json/.test(err.message)) {
    console.error('Source .mcp.json is corrupt. Fix JSON syntax and retry. Detail:', err.message);
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: Planning or applying a Kimi install (target: 'kimi') when the source repo's <repoRoot>/.mcp.json exists but is not valid JSON — trailing comma, unterminated string, single quotes, UTF-8 BOM, or a partially written file.

Common situations: Hand-edited .mcp.json with a syntax error; another tool mid-write when ECC read it; copy-paste introduced a trailing comma; editor saved with a BOM; JSONL content mistakenly placed in a .json file.

Understand the failure class

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/bda414a353367c2e. Report an issue: GitHub.