{"record":{"id":"3d07bbdca53a8c9d","repo":"affaan-m/ECC","slug":"cannot-merge-ecc-configuration-into-invalid-json-a","errorCode":null,"errorMessage":"Cannot merge ECC configuration into invalid JSON at ${destinationPath}: ${error.message}","messagePattern":"Cannot merge ECC configuration into invalid JSON at (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":194,"sourceCode":"      || currentFingerprint.sha256 !== operation.contentSha256.toLowerCase()\n    ) {\n      throw new Error(\n        `Refusing unverified ownership from install-state at ${plan.installStatePath}: `\n        + `content digest does not match ${destinationPath}.`\n      );\n    }\n    destinations.add(canonicalDestination);\n  }\n  return { destinations, stateFingerprint: validatedFingerprint };\n}\n\nfunction assertMergeDestination(destinationPath) {\n  if (!fs.existsSync(destinationPath)) return null;\n  let current;\n  try {\n    current = JSON.parse(fs.readFileSync(destinationPath, 'utf8'));\n  } catch (error) {\n    throw new Error(`Cannot merge ECC configuration into invalid JSON at ${destinationPath}: ${error.message}`);\n  }\n  if (!current || typeof current !== 'object' || Array.isArray(current)) {\n    throw new Error(`Cannot merge ECC configuration at ${destinationPath}: expected a JSON object.`);\n  }\n  return current;\n}\n\nfunction isPlainObject(value) {\n  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction findJsonConflicts(current, patch, prefix = '') {\n  if (!isPlainObject(patch)) return [];\n  return Object.entries(patch).flatMap(([key, patchValue]) => {\n    if (!Object.prototype.hasOwnProperty.call(current, key)) return [];\n    const currentValue = current[key];\n    const field = prefix ? `${prefix}.${key}` : key;\n    if (isPlainObject(currentValue) && isPlainObject(patchValue)) {","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/multi-harness-setup.js#L176-L212","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before: tsconfig.json contains a comment -> JSON.parse throws\n// file: { \"compilerOptions\": { /* fix */ \"strict\": true } }\nclassifyManagedOperation(op, owned); // throws [289]\n\n// after: valid JSON\n// file: { \"compilerOptions\": { \"strict\": true } }","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nfunction assertMergeableJson(destinationPath) {\n  if (!fs.existsSync(destinationPath)) return;\n  JSON.parse(fs.readFileSync(destinationPath, 'utf8')); // throws on invalid JSON\n}\n// before classify/apply, for each merge-json destination:\nassertMergeableJson(operation.destinationPath);","typeGuard":"function isParsableJson(filePath) {\n  try {\n    if (!require('fs').existsSync(filePath)) return true;\n    JSON.parse(require('fs').readFileSync(filePath, 'utf8'));\n    return true;\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  classifyManagedOperation(operation, ownedDestinations);\n} catch (err) {\n  if (/invalid JSON at/.test(err.message)) {\n    // surface the path + underlying parse error to the user, do not auto-overwrite\n    throw new Error(`Fix the JSON at ${operation.destinationPath} before ECC can merge into it.`);\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["merge-json","json-parse","configuration","validation","kimi"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}