nexu-io/open-design · error · Error

existing config at ${where} is not valid JSON: ${err instanc

Error message

existing config at ${where} is not valid JSON: ${err instanceof Error ? err.message : String(err)}

What it means

Thrown by parseJsonObject() in the MCP agent install pipeline when the existing target config file (e.g. claude_desktop_config.json, ~/.codex/config.json) exists but JSON.parse() throws a SyntaxError. The install pipeline refuses to overwrite a config it cannot parse, to avoid silently destroying a user's hand-maintained configuration. The error message includes the file path (`where`) and the underlying parse error.

Source

Thrown at apps/daemon/src/mcp-agent-install.ts:421

  for (const key of plan.keyPath) {
    const next = cursor[key];
    if (next == null || typeof next !== 'object' || Array.isArray(next)) {
      return null;
    }
    cursor = next as Record<string, unknown>;
  }
  if (!(plan.serverKey in cursor)) return null;
  delete cursor[plan.serverKey];
  return `${JSON.stringify(root, null, 2)}\n`;
}

function parseJsonObject(text: string | null, where: string): Record<string, unknown> {
  if (text == null || text.trim() === '') return {};
  let parsed: unknown;
  try {
    parsed = JSON.parse(text);
  } catch (err) {
    throw new Error(
      `existing config at ${where} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,
    );
  }
  if (parsed == null || typeof parsed !== 'object' || Array.isArray(parsed)) {
    throw new Error(`existing config at ${where} is not a JSON object`);
  }
  return parsed as Record<string, unknown>;
}

// --- Snippets for the manual (print-only) strategy ----------------------

function genericMcpServersSnippet(spec: McpLaunchSpec, name: string): string {
  const server: Record<string, unknown> = {
    command: spec.command,
    args: spec.args,
  };
  if (Object.keys(spec.env).length > 0) server.env = spec.env;
  return JSON.stringify({ mcpServers: { [name]: server } }, null, 2);

View on GitHub (pinned to 5be4028344)

Solutions

  1. Open the file at the path in the error message and fix the JSON syntax error (remove trailing commas, quote keys, remove comments).
  2. Validate with `node -e 'JSON.parse(require("fs").readFileSync("<path>","utf8"))'` or `jq . <path>`.
  3. If the file is JSONC/JSON5, convert it to plain JSON before running the install.
  4. Back up and regenerate the file from scratch if it is beyond quick repair.

Example fix

// before (~/.config/claude/claude_desktop_config.json)
{
  "mcpServers": {
    "foo": { "command": "foo" }, // trailing comma below
  }
}
// after
{
  "mcpServers": {
    "foo": { "command": "foo" }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

import { readFile } from 'node:fs/promises';

async function assertConfigParses(configPath: string): Promise<void> {
  const text = await readFile(configPath, 'utf8').catch(() => null);
  if (text == null || text.trim() === '') return;
  try {
    JSON.parse(text);
  } catch (err) {
    throw new Error(`Refusing to install: ${configPath} is not valid JSON (${(err as Error).message}). Fix or back up the file first.`);
  }
}

await assertConfigParses(plan.configPath);

Try / catch

try {
  applyJsonInstall(existingText, plan);
} catch (error) {
  if (error instanceof Error && error.message.includes('is not valid JSON')) {
    // Prompt the user to fix the file at plan.configPath, then retry.
    throw new Error(`MCP install aborted: fix JSON syntax in ${plan.configPath} first.`);
  }
  throw error;
}

Prevention

When it happens

Trigger: Running `od mcp install` (or any flow that calls applyJsonInstall/removeJsonInstall) against a target config file containing a JSON syntax error: trailing comma, unquoted key, single-quoted string, JSX/JSON5 comment (`//` or `/* */`), or a literal BOM/corruption.

Common situations: User has hand-edited their claude_desktop_config.json and left a trailing comma or comment; config was written by a tool that emits JSON5/JSONC; file was partially written and truncated; CRLF/encoding issues.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/5941827d5494e5fb. Report an issue: GitHub.