{"record":{"id":"a37f1c30abe58801","repo":"bytedance/deer-flow","slug":"failed-to-update-mcp-server-state-str-e","errorCode":null,"errorMessage":"Failed to update MCP server state: {str(e)}","messagePattern":"Failed to update MCP server state: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/app/gateway/routers/mcp.py","lineNumber":970,"sourceCode":"    \"/mcp/config\",\n    response_model=McpConfigResponse,\n    summary=\"Update MCP Server State\",\n    description=\"Enable or disable one MCP server without replacing the full extensions configuration.\",\n)\nasync def update_mcp_server_state(request: Request, body: McpServerStateUpdateRequest) -> McpConfigResponse:\n    \"\"\"Enable or disable one MCP server and reload the MCP tool cache.\"\"\"\n    try:\n        await require_admin_user(request, detail=_ADMIN_REQUIRED_DETAIL)\n        reloaded_servers = await asyncio.to_thread(_apply_mcp_server_state_update, body)\n\n        servers = {name: _mask_server_config(McpServerConfigResponse(**server.model_dump())) for name, server in reloaded_servers.items()}\n        reset_mcp_tools_cache()\n        return McpConfigResponse(mcp_servers=servers)\n    except HTTPException:\n        raise\n    except Exception as e:\n        logger.error(\"Failed to update MCP server %s state: %s\", body.server_name, e, exc_info=True)\n        raise HTTPException(status_code=500, detail=f\"Failed to update MCP server state: {str(e)}\")\n","sourceCodeStart":952,"sourceCodeEnd":971,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/mcp.py#L952-L971","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: stored server {\"command\": \"/opt/srv/run.sh\"} -> enable -> 500 (validation fails)\n# after: PUT corrected definition first\n{\"my-server\": {\"type\": \"stdio\", \"command\": \"uvx\", \"args\": [\"my-server\"]}}\n# then PATCH {\"server_name\": \"my-server\", \"enabled\": true}","handlingStrategy":"try-catch","validationCode":"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');","typeGuard":"null","tryCatchPattern":"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; }","preventionTips":["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)"],"tags":["mcp","config","patch","http-500"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}