{"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":244,"sourceCode":"    ) {\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, existingSnapshot = null) {\n  const snapshot = existingSnapshot || readRegularFileSnapshot(destinationPath);\n  if (!snapshot) return null;\n  let current;\n  try {\n    current = JSON.parse(snapshot.content.toString('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":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/multi-harness-setup.js#L226-L262","documentation":"assertMergeDestination parses an existing merge-json destination file as JSON before ECC merges its configuration into it. If JSON.parse throws, the error is rethrown with this message naming the destination and the underlying parse error. ECC refuses to merge into malformed JSON because the merge would either fail or silently destroy the invalid content.","triggerScenarios":"Calling an install/plan operation with kind 'merge-json' (via classifyManagedOperation → assertMergeDestination) where the destination file exists but contains syntactically invalid JSON — trailing commas, comments, truncated writes, or a non-JSON file placed at the config path.","commonSituations":"A user hand-edited a harness config (e.g. agents/openai.yaml-style JSON or .mcp.json) and introduced a syntax error; a previous crashed write left a truncated file; someone renamed a JSONC file to .json keeping comments.","solutions":["Open the destination file, fix the JSON syntax error reported in error.message (line/column), then re-run the install.","If the file's content is disposable, delete it so the installer recreates it, then reapply intended settings as valid JSON.","Convert comments to valid JSON (or move the file to a JSONC path the tool actually supports) before installing."],"exampleFix":"// before: agents.json\n{ \"name\": \"x\", } // trailing comma\n// after\n{ \"name\": \"x\" }","handlingStrategy":"validation","validationCode":"function assertValidJsonObjectFile(p) {\n  if (!fs.existsSync(p)) return;\n  const parsed = JSON.parse(fs.readFileSync(p, 'utf8')); // throws with position info\n  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n    throw new Error(`${p} must contain a JSON object`);\n  }\n}\nassertValidJsonObjectFile(destinationPath);","typeGuard":"function isJsonObjectFile(p) {\n  try {\n    const v = JSON.parse(fs.readFileSync(p, 'utf8'));\n    return Boolean(v) && typeof v === 'object' && !Array.isArray(v);\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  await runInstall(plan);\n} catch (err) {\n  if (String(err.message).startsWith('Cannot merge ECC configuration into invalid JSON')) {\n    const file = err.message.match(/at (.+?):/)[1];\n    console.error(`Fix JSON syntax in ${file} or delete it and re-run.`);\n  } else throw err;\n}","preventionTips":["Validate config JSON files (node -e \"JSON.parse(...)\" or a linter) before running installs.","Never put comments or trailing commas in .json files; use proper JSONC paths if supported.","Write config files atomically (temp file + rename) to avoid truncated JSON.","Commit valid config files so a broken local edit is caught in review/CI."],"tags":["json","config","parse-error"],"backgroundTag":"json-parse-error","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}