bytedance/deer-flow · error · HTTPException
Failed to update MCP server state: {str(e)}
Error message
Failed to update MCP server state: {str(e)} What it means
500 raised when the single-server enable/disable path (_apply_mcp_server_state_update) fails unexpectedly after the 404 checks passed — e.g. JSON parse/write errors on extensions_config.json, validation failures when re-validating the enabled server through McpServerConfigResponse/_validate_mcp_update_request, or reload errors. Unlike the full-update path, the detail carries str(e) and the log names the server involved.
Source
Thrown at backend/app/gateway/routers/mcp.py:970
"/mcp/config",
response_model=McpConfigResponse,
summary="Update MCP Server State",
description="Enable or disable one MCP server without replacing the full extensions configuration.",
)
async def update_mcp_server_state(request: Request, body: McpServerStateUpdateRequest) -> McpConfigResponse:
"""Enable or disable one MCP server and reload the MCP tool cache."""
try:
await require_admin_user(request, detail=_ADMIN_REQUIRED_DETAIL)
reloaded_servers = await asyncio.to_thread(_apply_mcp_server_state_update, body)
servers = {name: _mask_server_config(McpServerConfigResponse(**server.model_dump())) for name, server in reloaded_servers.items()}
reset_mcp_tools_cache()
return McpConfigResponse(mcp_servers=servers)
except HTTPException:
raise
except Exception as e:
logger.error("Failed to update MCP server %s state: %s", body.server_name, e, exc_info=True)
raise HTTPException(status_code=500, detail=f"Failed to update MCP server state: {str(e)}")
View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Check the Gateway log 'Failed to update MCP server <name> state' for the underlying exception
- If validation of the stored entry failed, update that server's definition (command/args/env) to pass current validation before enabling it
- Confirm the config file and its directory are writable by the Gateway process
- Retry after resolving; PATCH is serialized under extensions_config_write_lock so a retry is safe
Example fix
# before: stored server {"command": "/opt/srv/run.sh"} -> enable -> 500 (validation fails)
# after: PUT corrected definition first
{"my-server": {"type": "stdio", "command": "uvx", "args": ["my-server"]}}
# then PATCH {"server_name": "my-server", "enabled": true} Defensive patterns
Strategy: try-catch
Validate before calling
const cfg = await getMcpConfig(); const srv = cfg.mcp_servers[body.server_name]; if (!srv) throw new Error('unknown server'); if ((srv.type ?? 'stdio') === 'stdio' && srv.command === '***') throw new Error('masked command in stored config; fix definition via PUT before enabling'); Type guard
null
Try / catch
try { await patchMcpState(name, enabled); } catch (e) { if (e.status === 500) { console.error(`enable/disable of ${name} failed:`, e.detail); /* check log, repair stored definition via PUT, retry PATCH once */ } throw e; } Prevention
- Update legacy server definitions to current validation rules before enabling them
- Keep the config directory writable by the Gateway user
- Serialize config mutations through one path (API or file editing, not both)
When it happens
Trigger: PATCH /api/mcp/config enabling a server whose stored raw JSON fails stdio allowlist validation; config file becomes unwritable (permissions, read-only mount); malformed JSON introduced by an external editor between the read and write inside the lock.
Common situations: Enabling a legacy server entry that predates the stdio command allowlist rules; containerized Gateway with a read-only config mount; operators hand-editing config while the API is being used.
Related errors
- Failed to update MCP configuration: {str(e)}
- Failed to load MCP configuration
- Failed to update MCP configuration
- Failed to update MCP server
- Cannot set extra config key '{key}' to masked value '***'; p
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/a37f1c30abe58801.
Report an issue: GitHub.