affaan-m/ECC · error
Failed to parse at
Error message
Failed to parse ${label} at ${filePath}: ${error.message} What it means
readJsonObject in the Cursor project install target reads a JSON config file (e.g. a Cursor settings or MCP file) and, if the file is missing, unreadable, or not valid JSON, throws with the file path and the underlying parse error. Unlike plain JSON.parse errors, this one tells you which labeled file in the install operation failed.
Solutions
- Open the file at the path in the message and fix the JSON syntax error named in error.message
- If the file is JSONC (with comments), strip comments or move the config to a plain-JSON location before installing
- If unreadable due to permissions, fix chmod/chown on the file
- If the file is beyond repair, back it up and delete it so the installer can create a fresh one
Example fix
// before: .cursor/mcp.json with a trailing comma
{ "mcpServers": { "context7": { "command": "npx", } } }
// after
{ "mcpServers": { "context7": { "command": "npx" } } } Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: ensure the destination file is valid JSON before install
try {
JSON.parse(fs.readFileSync(cursorConfigPath, 'utf8'));
} catch (e) {
console.error(`Fix ${cursorConfigPath} before installing: ${e.message}`);
} Type guard
function isPlainObject(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v);
} Try / catch
try {
runInstallOperation(op);
} catch (e) {
if (/Failed to parse .* at .*:/.test(e.message)) {
// point the user at the file path in the message to fix its JSON
} else throw e;
} Prevention
- Keep Cursor config files as strict JSON — no comments or trailing commas
- Run `node -e "JSON.parse(...)` on config files after hand edits
- Avoid interrupting installs; a partial write leaves unparseable JSON
- Editor plugins that lint JSON catch this before the installer does
When it happens
Trigger: createJsonMergeOperation for a Cursor project target encounters a destination file that exists but contains invalid JSON (trailing commas, comments, truncation) or cannot be read (permissions/ENOENT on a path expected to exist for merging).
Common situations: A Cursor config file was hand-edited with JSONC-style comments; a crashed editor or install left a half-written file; the file was saved with a BOM or encoding issue that breaks JSON.parse.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse at
- Invalid at : expected a JSON object
- Failed to read
- Invalid at : expected a JSON object
- application request must be a JSON object
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/83c1963c5d929ed3.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install-targets/cursor-project.js:28
isForeignPlatformPath,
} = require('./helpers');
function toCursorRuleFileName(fileName, sourceRelativeFile) {
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,View on GitHub (pinned to 8321021c54)