{"record":{"id":"dba719d5d0df59ae","repo":"bytedance/deer-flow","slug":"failed-to-update-mcp-configuration-str-e","errorCode":null,"errorMessage":"Failed to update MCP configuration: {str(e)}","messagePattern":"Failed to update MCP configuration: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/app/gateway/routers/mcp.py","lineNumber":948,"sourceCode":"        await require_admin_user(request, detail=_ADMIN_REQUIRED_DETAIL)\n        _validate_mcp_update_request(body)\n\n        # Offload the blocking read-modify-write of extensions_config.json\n        # (path resolve, existence probe, raw read, merged write, reload). The\n        # worker takes extensions_config_write_lock for the whole RMW, so it stays\n        # atomic and serialized against the skills router (the other writer of\n        # this file) even if this request is cancelled mid-write.\n        reloaded_servers = await asyncio.to_thread(_apply_mcp_config_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\n    except HTTPException:\n        raise\n    except Exception as e:\n        logger.error(f\"Failed to update MCP configuration: {e}\", exc_info=True)\n        raise HTTPException(status_code=500, detail=f\"Failed to update MCP configuration: {str(e)}\")\n\n\n@router.patch(\n    \"/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:","sourceCodeStart":930,"sourceCodeEnd":966,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/mcp.py#L930-L966","documentation":"500 raised when _apply_mcp_config_update fails with an unexpected (non-HTTP) exception while applying a full MCP config update: JSON decode errors in extensions_config.json, permission failures writing the file, pydantic validation of stored raw entries, or errors in reload_extensions_config. The original exception is logged with traceback; its str(e) is intentionally included in the detail for diagnosability.","triggerScenarios":"PUT /api/mcp/config when extensions_config.json is corrupted JSON; the Gateway process lacks write permission on the config file; a pre-existing raw server entry fails model validation during reload; disk full during the atomic write.","commonSituations":"Hand-edited config files with syntax errors; read-only volumes in containers; concurrent external edits racing the API write; leftover invalid entries from older config schemas.","solutions":["Read the Gateway log line 'Failed to update MCP configuration' — the included str(e) plus traceback pinpoints the failure","Validate extensions_config.json parses (python -m json.tool) and fix syntax errors","Ensure the Gateway process can write the config file and directory (atomic rename needs directory write access)","If a stored entry fails validation, remove or repair it via direct file edit, then retry the API update"],"exampleFix":"# before: corrupted extensions_config.json -> 500 on every PUT\n# after\npython -m json.tool extensions_config.json   # locate and fix the syntax error\n# then retry PUT /api/mcp/config","handlingStrategy":"try-catch","validationCode":"// pre-flight: ensure the config file parses before PUT\n// python -c \"import json;json.load(open('extensions_config.json'))\"","typeGuard":"null","tryCatchPattern":"try { await putMcpConfig(payload); } catch (e) { if (e.status === 500) { console.error('server-side apply failed:', e.detail); /* read Gateway log; fix config/permissions; retry once */ } throw e; }","preventionTips":["Validate extensions_config.json with a JSON linter after any hand edit","Give the Gateway write access to the config file and its directory (atomic rename needs both)","Avoid editing the file externally while API-driven updates are in flight"],"tags":["mcp","config","http-500","filesystem"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}