BloopAI/vibe-kanban · error
Expected object at path: ${mcp_config.servers_path.join('.')
Error message
Expected object at path: ${mcp_config.servers_path.join('.')} What it means
validateFullConfig walks mcp_config.servers_path key-by-key through the full (raw app) config JSON. Before reading each key it asserts the current value is a JSON object; if a mid-path value is an array, string, number, or null it throws this error. It guards against traversing into a non-object when locating the MCP servers section.
Source
Thrown at packages/web-core/src/shared/lib/mcpStrategies.ts:37
: undefined;
if (!next) current[key] = {};
current = current[key] as JsonObject;
}
if (cfg.servers_path.length > 0) {
const lastKey = cfg.servers_path[cfg.servers_path.length - 1];
current[lastKey] = cfg.servers;
}
return fullConfig;
}
static validateFullConfig(
mcp_config: McpConfig,
full_config: JsonValue
): void {
let current: JsonValue = full_config;
for (const key of mcp_config.servers_path) {
if (!isJsonObject(current)) {
throw new Error(
`Expected object at path: ${mcp_config.servers_path.join('.')}`
);
}
current = current[key];
if (current === undefined) {
throw new Error(
`Missing required field at path: ${mcp_config.servers_path.join('.')}`
);
}
}
if (!isJsonObject(current)) {
throw new Error('Servers configuration must be an object');
}
}
static extractServersForApi(
mcp_config: McpConfig,
full_config: JsonValue
): JsonObject {View on GitHub (pinned to 4deb7eca8f)
Solutions
- Log/print full_config and compare each segment of servers_path against its actual shape.
- Fix the config so every segment except the last is a JSON object, or correct servers_path to match the real structure.
- If migrating from another tool's config format, use the matching McpConfig strategy rather than reusing servers_path.
- Validate the config JSON before calling handleMcpServersChange/handleApplyMcpServers.
Example fix
// before: path points into a scalar
validateFullConfig(cfg, { mcp: 'not-an-object' }); // throws
// after: ensure the container is an object first
const full = { mcp: { servers: {} } };
validateFullConfig(cfg, full); Defensive patterns
Strategy: validation
Validate before calling
function pathIsTraversable(full, path) {
let cur = full;
for (const k of path) {
if (typeof cur !== 'object' || cur === null || Array.isArray(cur)) return false;
cur = cur[k];
}
return true;
}
if (!pathIsTraversable(fullConfig, cfg.servers_path)) console.warn('Config not traversable at', cfg.servers_path.join('.')); Type guard
function isJsonObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Try / catch
try {
McpConfigStrategyGeneral.validateFullConfig(cfg, fullConfig);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Expected object at path')) {
fullConfig = McpConfigStrategyGeneral.createFullConfig(cfg); // rebuild
} else throw e;
} Prevention
- Validate config JSON shape before passing it into strategy handlers
- Keep servers_path in sync with the target MCP client's documented schema
- Schema-check hand-edited config files before loading them
- Don't share one servers_path across different MCP strategies
When it happens
Trigger: servers_path contains a key whose current value is not an object — e.g. path ['mcp','servers'] but full_config.mcp is a string/number/boolean/array/null; a user hand-edited the config file so a path segment holds a scalar.
Common situations: A config for one MCP strategy (e.g. a 'mcpServers' object path) applied to a config file shaped for another tool; manual edits corrupting the file; a template that defines a segment as an array.
Related errors
- Missing required field at path: ${mcp_config.servers_path.jo
- Servers configuration must be an object
- Unknown preconfigured server '${serverKey}'
- Provide `prompt`, or `issue_id` that has a non-empty title/d
- Failed to list projects (${res.status})
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/60fe45f2afedac0c.
Report an issue: GitHub.