{"record":{"id":"60691a93d5f79ef3","repo":"can1357/oh-my-pi","slug":"server-name-was-disconnected-during-reconnect","errorCode":null,"errorMessage":"Server \"${name}\" was disconnected during reconnection","messagePattern":"Server \"(.+?)\" was disconnected during reconnection","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/coding-agent/src/mcp/manager.ts","lineNumber":1211,"sourceCode":"\t\tconst resolvedConfig = await this.#resolveAuthConfig(config);\n\t\tconst connection = await connectToServer(name, resolvedConfig, {\n\t\t\tonNotification: (method, params) => {\n\t\t\t\tthis.#handleServerNotification(name, method, params);\n\t\t\t},\n\t\t\tonRequest: (method, params) => {\n\t\t\t\treturn this.#handleServerRequest(method, params);\n\t\t\t},\n\t\t});\n\n\t\tconnection.config = config;\n\t\tif (source) connection._source = source;\n\n\t\t// Bail out if the server was disconnected or the manager was reset\n\t\t// while we were connecting (e.g. /mcp reload called disconnectAll).\n\t\tif (!this.#serverConfigs.has(name) || this.#epoch !== reconnectEpoch) {\n\t\t\tthis.#detachConnection(name, connection);\n\t\t\tvoid disconnectServer(connection).catch(() => {});\n\t\t\tthrow new Error(`Server \"${name}\" was disconnected during reconnection`);\n\t\t}\n\n\t\tthis.#connections.set(name, connection);\n\n\t\t// Wire auth refresh for HTTP-like transports, and reconnect for any transport.\n\t\t// Same gate as connectServers: any resolvable managed credential.\n\t\tif (isAuthRefreshableMCPTransport(connection.transport) && lookupMcpOAuthCredential(this.#authStorage, config)) {\n\t\t\tconnection.transport.onAuthError = async () => {\n\t\t\t\tconst refreshed = await this.#resolveAuthConfig(config, { forceRefresh: true });\n\t\t\t\tif (refreshed.type === \"http\" || refreshed.type === \"sse\") {\n\t\t\t\t\treturn refreshed.headers ?? null;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t};\n\t\t}\n\t\tconnection.transport.onClose = () => {\n\t\t\tlogger.debug(\"MCP transport lost, triggering reconnect\", { path: `mcp:${name}` });\n\t\t\tthis.#emitConnectionStatus({ type: \"connecting\", serverNames: [name] });","sourceCodeStart":1193,"sourceCodeEnd":1229,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/mcp/manager.ts#L1193-L1229","documentation":"During a background reconnection, after the connection is re-established the manager re-checks whether the server still has a config entry and whether the manager epoch changed while connecting (e.g. /mcp reload called disconnectAll). If either happened, it detaches and disconnects the fresh connection and throws this error naming the server. It is the reconnection-path twin of error 1747.","triggerScenarios":"A pending reconnection for server \"name\" completes while: the server's config entry was removed (#serverConfigs no longer has the name), disconnectAll/reset bumped #epoch (config reload, shutdown), or another lifecycle change invalidated the reconnect epoch.","commonSituations":"User runs /mcp reload while a dropped server is mid-reconnect; server is removed from config but its auto-reconnect was still in flight; manager reset/shutdown overlapping a reconnect after a network blip or server crash; OAuth refresh triggering reconnect just as config changes.","solutions":["Retry the reconnection after the reload/disconnect operation finishes.","If the server is genuinely removed, don't reconnect — the error is expected; filter removed servers from reconnect lists.","Avoid triggering config reload or disconnectAll while reconnects are in flight; await them.","Re-read the current config to confirm the server still exists before attempting reconnect.","Catch and swallow this error in fire-and-forget reconnect paths where the server was intentionally removed."],"exampleFix":"// before\nvoid manager.reconnect(\"github\"); // later /mcp reload cancels it -> throws\n// after\ntry {\n  await manager.reconnect(\"github\");\n} catch (e) {\n  if (e instanceof Error && /disconnected during reconnection/.test(e.message)) return; // removed by reload\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"import { readMCPConfigFile } from \"@oh-my-pi/pi-coding-agent/mcp/config\";\nconst cfg = await readMCPConfigFile(configPath);\nif (!cfg.mcpServers?.[name]) return; // server removed; skip reconnect entirely","typeGuard":"null","tryCatchPattern":"try {\n  await manager.reconnect(name);\n} catch (e) {\n  if (e instanceof Error && /was disconnected during reconnection/.test(e.message)) {\n    return; // intentional removal or reload; not an operator-visible failure\n  }\n  throw e;\n}","preventionTips":["Skip auto-reconnect for servers no longer present in the current config.","Avoid /mcp reload or disconnectAll while reconnects are in flight, or await them first.","In fire-and-forget reconnect code, catch and swallow this specific error.","Sequence config edits and reconnects so they don't overlap."],"tags":["mcp","race-condition","reconnection","lifecycle"],"backgroundTag":"connection-cancelled-during-setup","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}