nexu-io/open-design · error · Error
existing config at ${where} is not a JSON object
Error message
existing config at ${where} is not a JSON object What it means
Thrown by parseJsonObject() after JSON.parse() succeeds but the parsed value is not a JSON object — i.e. it is null, an array, or a primitive (string/number/boolean). MCP client config roots must be objects (so a server entry can be inserted at a key path like `mcpServers.<name>`); a non-object root cannot host the nested key path the installer needs.
Source
Thrown at apps/daemon/src/mcp-agent-install.ts:426
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);
}
function hermesYamlSnippet(spec: McpLaunchSpec, name: string): string {
const lines = [
'mcp_servers:',View on GitHub (pinned to 5be4028344)
Solutions
- Rewrite the file so its root is a JSON object `{ ... }` with the expected key path (commonly `mcpServers`).
- If you genuinely need a list format for another tool, point the installer at a different config file or migrate the data into object form.
- Confirm with `jq -e 'type == "object"' <path>` that the root is an object.
Example fix
// before (config.json)
[
{ "name": "foo", "command": "foo" }
]
// after
{
"mcpServers": {
"foo": { "command": "foo" }
}
} Defensive patterns
Strategy: validation
Validate before calling
function isJsonObjectRoot(text: string | null): boolean {
if (text == null || text.trim() === '') return true; // empty is treated as {}
let v: unknown;
try { v = JSON.parse(text); } catch { return false; }
return v !== null && typeof v === 'object' && !Array.isArray(v);
}
if (!isJsonObjectRoot(existingText)) {
throw new Error(`Config root must be a JSON object; migrate or pick another file.`);
} Type guard
function isPlainJsonObject(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === 'object' && !Array.isArray(value);
} Try / catch
try {
applyJsonInstall(existingText, plan);
} catch (error) {
if (error instanceof Error && error.message.includes('is not a JSON object')) {
throw new Error(`Config root at ${plan.configPath} is not an object; restructure it as { ... } first.`);
}
throw error;
} Prevention
- Maintain MCP client config roots as objects keyed by `mcpServers` (or the host's convention).
- Do not let other tools overwrite the config with a list or scalar.
- Validate root shape with `jq -e 'type == "object"'` after edits.
When it happens
Trigger: Target config file contains a bare array (`[{...}]`), a bare string, a bare number, or the literal `null` at its root. Example: a codex config that was accidentally written as an array of server entries.
Common situations: User restructured their config file to a list format; another tool overwrote the config with a non-object schema; file was hand-edited to `null` to 'disable' it.
Related errors
- existing config at ${where} is not valid JSON: ${err instanc
- Unsupported container: {config['container']}
- invalid JSON in ${filePath}: ${message}
- ${filePath} must contain a JSON object
- proposal patch.after is not valid JSON
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/1adfd78aa3eb1ca2.
Report an issue: GitHub.