{"record":{"id":"52399ce0b70f2e46","repo":"EveryInc/compound-engineering-plugin","slug":"warning-existing-configpath-is-not-valid-json","errorCode":null,"errorMessage":"Warning: existing ${configPath} is not valid JSON. Writing plugin config without merging.","messagePattern":"Warning: existing (.+?) is not valid JSON\\. Writing plugin config without merging\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/targets/opencode.ts","lineNumber":57,"sourceCode":"  }\n  if (!manifest?.groups[group]?.includes(entryName)) {\n    console.warn(`Skipping ${targetPath}: existing unmanaged file (not overwritten)`)\n    return true\n  }\n  return false\n}\n\nasync function mergeOpenCodeConfig(\n  configPath: string,\n  incoming: OpenCodeConfig,\n): Promise<OpenCodeConfig> {\n  if (!(await pathExists(configPath))) return incoming\n\n  let existing: OpenCodeConfig\n  try {\n    existing = await readJson<OpenCodeConfig>(configPath)\n  } catch {\n    console.warn(\n      `Warning: existing ${configPath} is not valid JSON. Writing plugin config without merging.`\n    )\n    return incoming\n  }\n\n  const mergedMcp = {\n    ...(incoming.mcp ?? {}),\n    ...(existing.mcp ?? {}),\n  }\n\n  const mergedPermission = incoming.permission\n    ? {\n        ...(incoming.permission),\n        ...(existing.permission ?? {}),\n      }\n    : existing.permission\n\n  const mergedTools = incoming.tools","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/EveryInc/compound-engineering-plugin/blob/c9c10f8c75412c7232cb2bd663e5fd1cea98d84e/src/targets/opencode.ts#L39-L75","documentation":"mergeOpenCodeConfig in src/targets/opencode.ts deep-merges incoming plugin configuration (MCP servers etc.) into the existing opencode.json. If the existing file cannot be parsed as JSON, the merge is abandoned with this warning and only the incoming config is written — the user's existing (invalid) config content is not merged, so any custom keys in it will be lost from the output.","triggerScenarios":"readJson<OpenCodeConfig>(configPath) throws during an OpenCode bundle write because the existing configPath (opencode.json) contains malformed JSON — trailing commas, comments, BOM, truncated writes, or the file actually being JSONC.","commonSituations":"Users hand-editing opencode.json and introducing a syntax error; tools that write JSONC (comments allowed) into opencode.json; a crashed editor or partial write leaving a truncated file; copying a config.jsonc over opencode.json.","solutions":["Validate and repair the existing file: run it through `jq . opencode.json` or a JSON linter, fix the syntax error, then re-run the install so a proper merge occurs.","If the file intentionally contains comments (JSONC), move comments out — opencode.json must be strict JSON for the merge to work.","Back up the current file before re-running, since the next install will overwrite it with only the incoming plugin config.","After repairing, re-run the install and confirm the warning no longer appears and your custom keys survived the merge."],"exampleFix":"// before: opencode.json with comment/trailing comma\n{ \"mcp\": { ... }, // my comment\n}\n// after: strict JSON\n{\n  \"mcp\": { \"...\": \"...\" }\n}","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs'\nfunction assertStrictJson(filePath: string): void {\n  if (!existsSync(filePath)) return\n  JSON.parse(require('node:fs').readFileSync(filePath, 'utf8')) // throws on invalid/JSONC\n}\nassertStrictJson('opencode.json') // run before install","typeGuard":null,"tryCatchPattern":"try {\n  installOpenCode()\n} catch (err) {\n  // merge warnings go to console.warn, not throw — check output\n  if (!jsonIsValid('opencode.json')) {\n    console.error('opencode.json is not strict JSON; fix it before reinstalling to avoid losing custom keys')\n  }\n}","preventionTips":["Keep opencode.json strict JSON — no comments, trailing commas, or BOM","Run `jq . opencode.json` (or a linter) as a pre-commit check after hand edits","Keep custom config in a separate tracked copy so a bad merge is recoverable"],"tags":["json","opencode","config-merge","parse-error"],"backgroundTag":"invalid-json-config","analyzedSha":"c9c10f8c75412c7232cb2bd663e5fd1cea98d84e","analyzedAt":"2026-08-31T15:18:07.959Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}