bytedance/deer-flow · error · MCPConfigRequestError
Failed to update MCP configuration
Error message
Failed to update MCP configuration
What it means
Thrown when PUT /api/mcp/config (full replacement of the MCP server configuration) returns non-2xx. The Gateway re-validates and atomically writes extensions_config.json; a 422 means the submitted MCPConfig failed schema validation (bad command/args/env types), while 500 usually means the file could not be written.
Source
Thrown at frontend/src/core/mcp/api.ts:48
if (!response.ok) {
throw new MCPConfigRequestError(
response.status,
await readErrorDetail(response, "Failed to load MCP configuration"),
);
}
return response.json() as Promise<MCPConfig>;
}
export async function updateMCPConfig(config: MCPConfig) {
const response = await fetch(`${getBackendBaseURL()}/api/mcp/config`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(config),
});
if (!response.ok) {
throw new MCPConfigRequestError(
response.status,
await readErrorDetail(response, "Failed to update MCP configuration"),
);
}
return response.json();
}
export async function updateMCPServerState(
serverName: string,
enabled: boolean,
) {
const response = await fetch(`${getBackendBaseURL()}/api/mcp/config`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
server_name: serverName,View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Read the 422 'detail' — FastAPI lists the exact failing JSON path and expected type
- Fix the offending server entry in the editor and re-PUT
- Ensure the process running the Gateway can write extensions_config.json (check mount flags in docker-compose)
- Reload GET /api/mcp/config to see the server's current canonical shape and diff your payload against it
Example fix
// before
await updateMCPConfig(editedConfig);
// after
try {
await updateMCPConfig(editedConfig);
} catch (e) {
if (e instanceof MCPConfigRequestError && e.status === 422) {
setFormErrors(e.message); // FastAPI detail names the invalid field
return;
}
throw e;
} Defensive patterns
Strategy: validation
Validate before calling
function validateMCPConfig(config: MCPConfig): string[] {
const errs: string[] = [];
for (const [name, srv] of Object.entries(config.mcpServers ?? {})) {
if ('command' in srv && !srv.command) errs.push(`${name}: command required for stdio`);
if ('url' in srv && !/^https?:\/\//.test(srv.url)) errs.push(`${name}: url must be http(s)`);
if (srv.env !== undefined && typeof srv.env !== 'object') errs.push(`${name}: env must be an object`);
}
return errs;
} Type guard
export function isMCPConfigRequestError(e: unknown): e is MCPConfigRequestError {
return e instanceof MCPConfigRequestError;
} Try / catch
try {
await updateMCPConfig(config);
} catch (e) {
if (isMCPConfigRequestError(e) && e.status === 422) {
setEditorErrors(e.message);
return;
}
throw e;
} Prevention
- Run schema validation in the editor before enabling Save
- Parse-and-stringify edited JSON in a try-catch to catch syntax errors client-side
- Ensure the config file is writable by the Gateway process
When it happens
Trigger: Saving the MCP editor with a server entry missing required fields (e.g. command empty for a stdio server), env not an object, or url malformed for an SSE/streamable server; concurrent edits where two tabs PUT different configs; filesystem permission loss on the repo root.
Common situations: Editing the JSON textarea directly and leaving a trailing comma or quoting a number; switching a server between stdio and SSE types without clearing stale fields; running the Gateway in Docker where extensions_config.json is mounted read-only.
Related errors
- Failed to load MCP configuration
- Failed to update MCP server
- Failed to load suggestions config: ${response.statusText}
- MCP server '{server_name}' with stdio transport requires a c
- HTTP ${response.status}: ${response.statusText}
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/b746b33f4b62d4b4.
Report an issue: GitHub.