EveryInc/compound-engineering-plugin · warning

Warning: existing ${configPath} is not valid JSON. Writing p

Error message

Warning: existing ${configPath} is not valid JSON. Writing plugin config without merging.

What it means

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.

Source

Thrown at src/targets/opencode.ts:57

  }
  if (!manifest?.groups[group]?.includes(entryName)) {
    console.warn(`Skipping ${targetPath}: existing unmanaged file (not overwritten)`)
    return true
  }
  return false
}

async function mergeOpenCodeConfig(
  configPath: string,
  incoming: OpenCodeConfig,
): Promise<OpenCodeConfig> {
  if (!(await pathExists(configPath))) return incoming

  let existing: OpenCodeConfig
  try {
    existing = await readJson<OpenCodeConfig>(configPath)
  } catch {
    console.warn(
      `Warning: existing ${configPath} is not valid JSON. Writing plugin config without merging.`
    )
    return incoming
  }

  const mergedMcp = {
    ...(incoming.mcp ?? {}),
    ...(existing.mcp ?? {}),
  }

  const mergedPermission = incoming.permission
    ? {
        ...(incoming.permission),
        ...(existing.permission ?? {}),
      }
    : existing.permission

  const mergedTools = incoming.tools

View on GitHub (pinned to c9c10f8c75)

Solutions

  1. 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.
  2. If the file intentionally contains comments (JSONC), move comments out — opencode.json must be strict JSON for the merge to work.
  3. Back up the current file before re-running, since the next install will overwrite it with only the incoming plugin config.
  4. After repairing, re-run the install and confirm the warning no longer appears and your custom keys survived the merge.

Example fix

// before: opencode.json with comment/trailing comma
{ "mcp": { ... }, // my comment
}
// after: strict JSON
{
  "mcp": { "...": "..." }
}
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs'
function assertStrictJson(filePath: string): void {
  if (!existsSync(filePath)) return
  JSON.parse(require('node:fs').readFileSync(filePath, 'utf8')) // throws on invalid/JSONC
}
assertStrictJson('opencode.json') // run before install

Try / catch

try {
  installOpenCode()
} catch (err) {
  // merge warnings go to console.warn, not throw — check output
  if (!jsonIsValid('opencode.json')) {
    console.error('opencode.json is not strict JSON; fix it before reinstalling to avoid losing custom keys')
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of EveryInc/compound-engineering-plugin@c9c10f8c75 (2026-08-31). Data as JSON: /api/errors/52399ce0b70f2e46. Report an issue: GitHub.