{"record":{"id":"0073746601da0b88","repo":"ChatGPTNextWeb/NextChat","slug":"server-clientid-not-found","errorCode":null,"errorMessage":"Server ${clientId} not found","messagePattern":"Server (.+?) not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"app/mcp/actions.ts","lineNumber":201,"sourceCode":"    // 只有新服务器或状态为 active 的服务器才初始化\n    if (isNewServer || config.status === \"active\") {\n      await initializeSingleClient(clientId, config);\n    }\n\n    return newConfig;\n  } catch (error) {\n    logger.error(`Failed to add server [${clientId}]: ${error}`);\n    throw error;\n  }\n}\n\n// 暂停服务器\nexport async function pauseMcpServer(clientId: string) {\n  try {\n    const currentConfig = await getMcpConfigFromFile();\n    const serverConfig = currentConfig.mcpServers[clientId];\n    if (!serverConfig) {\n      throw new Error(`Server ${clientId} not found`);\n    }\n\n    // 先更新配置\n    const newConfig: McpConfigData = {\n      ...currentConfig,\n      mcpServers: {\n        ...currentConfig.mcpServers,\n        [clientId]: {\n          ...serverConfig,\n          status: \"paused\",\n        },\n      },\n    };\n    await updateMcpConfig(newConfig);\n\n    // 然后关闭客户端\n    const client = clientsMap.get(clientId);\n    if (client?.client) {","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/ChatGPTNextWeb/NextChat/blob/defdcdb55d850cd12c4c657eb83729fd66e215c0/app/mcp/actions.ts#L183-L219","documentation":"Thrown at app/mcp/actions.ts:201 inside pauseMcpServer when currentConfig.mcpServers[clientId] is undefined — i.e. the clientId passed in does not exist in the persisted MCP config file. The function reads the config from disk (getMcpConfigFromFile), looks up the server entry, and refuses to pause a server it cannot find.","triggerScenarios":"Calling pauseMcpServer(clientId) where clientId was never added, was already removed (removeMcpServer deleted the key), or where the config file on disk was hand-edited and the entry deleted between the UI listing and the pause click.","commonSituations":"Stale UI state: the server list was rendered, then the config changed (removed by another tab, external edit, or a restart that reset to defaults) before the user clicked pause; a typo or programmatic caller passing a wrong id; the config file does not exist and getMcpConfigFromFile fell back to DEFAULT_MCP_CONFIG which has no servers.","solutions":["Refresh the server list from getMcpConfigFromFile() before invoking pause and drop the call if the id is gone.","Verify the clientId exists in config.mcpServers before calling pauseMcpServer.","If the config file was lost, re-add the server via addMcpServer before pausing.","Treat 'not found' as a non-fatal no-op in the caller rather than an uncaught throw."],"exampleFix":"// before\npauseMcpServer(staleId).catch(console.error);\n\n// after\nconst config = await getMcpConfigFromFile();\nif (config.mcpServers[staleId]) {\n  await pauseMcpServer(staleId);\n} else {\n  showToast(`Server ${staleId} no longer exists`);\n}","handlingStrategy":"validation","validationCode":"import { getMcpConfigFromFile } from \"@/app/mcp/actions\";\n\nasync function serverExists(clientId: string): Promise<boolean> {\n  const config = await getMcpConfigFromFile();\n  return Boolean(config.mcpServers[clientId]);\n}\n\nif (await serverExists(id)) {\n  await pauseMcpServer(id);\n}","typeGuard":"function isServerInConfig(\n  config: McpConfigData,\n  clientId: string,\n): config is McpConfigData & { mcpServers: Record<string, ServerConfig> } {\n  return Boolean(config.mcpServers[clientId]);\n}","tryCatchPattern":"try {\n  await pauseMcpServer(id);\n} catch (e) {\n  if (e instanceof Error && /not found/.test(e.message)) {\n    showToast(`Server ${id} no longer exists`);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Re-read config immediately before mutating it; do not cache it across user actions.","Disable pause/resume buttons in the UI when the id disappears from the latest config.","Treat 'not found' as idempotent success for pause (the server is already not active)."],"tags":["mcp","config","state-mismatch","validation"],"backgroundTag":null,"analyzedSha":"defdcdb55d850cd12c4c657eb83729fd66e215c0","analyzedAt":"2026-08-12T09:57:26.489Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}