affaan-m/ECC · error · Error
Cannot merge ECC configuration into invalid JSON at ${destin
Error message
Cannot merge ECC configuration into invalid JSON at ${destinationPath}: ${error.message} What it means
Thrown by assertMergeDestination (called from classifyManagedOperation for kind:'merge-json') when the existing destination file fails JSON.parse. A merge-json operation can only merge into a valid JSON object, so a syntactically broken JSON file is a hard stop rather than a silent overwrite. The underlying parse error message is appended so the caller can see whether it was trailing commas, BOM, truncation, etc.
Source
Thrown at scripts/lib/multi-harness-setup.js:194
|| currentFingerprint.sha256 !== operation.contentSha256.toLowerCase()
) {
throw new Error(
`Refusing unverified ownership from install-state at ${plan.installStatePath}: `
+ `content digest does not match ${destinationPath}.`
);
}
destinations.add(canonicalDestination);
}
return { destinations, stateFingerprint: validatedFingerprint };
}
function assertMergeDestination(destinationPath) {
if (!fs.existsSync(destinationPath)) return null;
let current;
try {
current = JSON.parse(fs.readFileSync(destinationPath, 'utf8'));
} catch (error) {
throw new Error(`Cannot merge ECC configuration into invalid JSON at ${destinationPath}: ${error.message}`);
}
if (!current || typeof current !== 'object' || Array.isArray(current)) {
throw new Error(`Cannot merge ECC configuration at ${destinationPath}: expected a JSON object.`);
}
return current;
}
function isPlainObject(value) {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
}
function findJsonConflicts(current, patch, prefix = '') {
if (!isPlainObject(patch)) return [];
return Object.entries(patch).flatMap(([key, patchValue]) => {
if (!Object.prototype.hasOwnProperty.call(current, key)) return [];
const currentValue = current[key];
const field = prefix ? `${prefix}.${key}` : key;
if (isPlainObject(currentValue) && isPlainObject(patchValue)) {View on GitHub (pinned to 01e15490f0)
Solutions
- Open destinationPath and fix the JSON syntax error shown in error.message (remove comments, trailing commas, conflict markers).
- If the file is JSONC by intention, convert it to plain JSON or move the configuration to a file ECC can parse.
- Resolve any git merge conflict markers in the file.
- If the file is irreparable, back it up, delete it so ECC treats the destination as absent (create), then re-run the preview.
Example fix
// before: tsconfig.json contains a comment -> JSON.parse throws
// file: { "compilerOptions": { /* fix */ "strict": true } }
classifyManagedOperation(op, owned); // throws [289]
// after: valid JSON
// file: { "compilerOptions": { "strict": true } } Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
function assertMergeableJson(destinationPath) {
if (!fs.existsSync(destinationPath)) return;
JSON.parse(fs.readFileSync(destinationPath, 'utf8')); // throws on invalid JSON
}
// before classify/apply, for each merge-json destination:
assertMergeableJson(operation.destinationPath); Type guard
function isParsableJson(filePath) {
try {
if (!require('fs').existsSync(filePath)) return true;
JSON.parse(require('fs').readFileSync(filePath, 'utf8'));
return true;
} catch { return false; }
} Try / catch
try {
classifyManagedOperation(operation, ownedDestinations);
} catch (err) {
if (/invalid JSON at/.test(err.message)) {
// surface the path + underlying parse error to the user, do not auto-overwrite
throw new Error(`Fix the JSON at ${operation.destinationPath} before ECC can merge into it.`);
}
throw err;
} Prevention
- Validate JSON config files in your editor (JSON language mode, not JSONC) before saving.
- Resolve git merge conflicts in JSON files before running install.
- Avoid comments/trailing commas in files ECC will merge.
- Add a pre-install JSON lint step for merge targets.
When it happens
Trigger: Fires when fs.readFileSync(destinationPath) succeeds but JSON.parse throws, for an operation with kind 'merge-json'. Common when a merge target (e.g., a settings JSON ECC wants to patch) has been hand-edited with a syntax error, was partially written by a crashed process, has a stray BOM/comment (JSONC) that strict JSON.parse rejects, or was corrupted by a merge conflict.
Common situations: Hand-editing tsconfig.json/.eslintrc/settings.json and leaving a trailing comma or comment; a git merge conflict left conflict markers inside the JSON; an editor saving as JSONC with comments; truncated file from a killed process; wrong encoding (UTF-16 BOM).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Cannot merge ECC configuration at ${destinationPath}: expect
- Invalid Kimi install profile: ${profile}
- Refusing to overwrite unowned JSON fields at ${destinationPa
- Invalid mode "${mode}". Allowed modes: ${allowedModes.join('
- Missing merge payload for repair: ${operation.destinationPat
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/3d07bbdca53a8c9d.
Report an issue: GitHub.