{"record":{"id":"83c218a3242bf721","repo":"Hmbown/CodeWhale","slug":"mcp-connection-disappeared-for-server-name","errorCode":null,"errorMessage":"MCP connection disappeared for {server_name}","messagePattern":"MCP connection disappeared for (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":2657,"sourceCode":"                    .and_then(|config| config.reviewed_plugin.clone())\n            });\n        if let Some(source) = plugin_source\n            && let Err(error) = source.validate_before_use(server_name, \"use\")\n        {\n            self.drop_connection(server_name, \"plugin authority revoked or changed\");\n            return Err(error);\n        }\n\n        let is_ready = self\n            .connections\n            .get(server_name)\n            .map(|conn| conn.is_ready())\n            .unwrap_or(false);\n        if is_ready {\n            return self\n                .connections\n                .get_mut(server_name)\n                .ok_or_else(|| anyhow::anyhow!(\"MCP connection disappeared for {server_name}\"));\n        }\n\n        self.drop_connection(server_name, \"reconnect\");\n\n        // Check static config first, then dynamic servers\n        let server_config = self\n            .config\n            .servers\n            .get(server_name)\n            .cloned()\n            .or_else(|| self.dynamic_servers.read().get(server_name).cloned())\n            .ok_or_else(|| anyhow::anyhow!(\"Failed to find MCP server: {server_name}\"))?;\n\n        if !server_config.is_enabled() {\n            anyhow::bail!(\"Failed to connect MCP server '{server_name}': server is disabled\");\n        }\n\n        let mut connection = McpConnection::connect_with_policy(","sourceCodeStart":2639,"sourceCodeEnd":2675,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L2639-L2675","documentation":"In get_or_connect, the code first checks connections.get(server_name) and reads is_ready(); if ready it immediately calls connections.get_mut(server_name). Because &mut self borrows the map exclusively between the two lookups and no code runs in between that could remove the entry, a None here would require the map to lose an entry with no mutation — i.e. a broken internal invariant (concurrent aliasing or memory corruption), not a user condition.","triggerScenarios":"Effectively unreachable in correct code: requires the HashMap to yield Some on get and None on get_mut for the same key with no intervening mutation, which cannot happen under the exclusive borrow.","commonSituations":"Not hit in practice; would only appear if a future refactor moved an await or a removal between the readiness check and the get_mut, or if unsafe aliasing of the pool existed. Seeing it means an internal regression, not a configuration problem.","solutions":["Report it as an internal bug against the mcp module with the reproduction steps; do not try to fix it via config.","If hacking on the pool: audit for any await, lock, or removal inserted between the is_ready check and get_mut in get_or_connect.","Retry via get_or_connect once — if it persists, the connections map is genuinely inconsistent and the process state is suspect."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust: invariant breach — report, attempt one clean retry\nmatch pool.get_or_connect(name).await {\n    Err(e) if e.to_string().contains(\"connection disappeared\") => {\n        tracing::error!(\"internal invariant broken in McpPool: {e:#}\");\n        pool.get_or_connect(name).await // one retry on a possibly-consistent map\n    }\n    o => o,\n}","preventionTips":["Treat this error as a bug report trigger, not a config problem.","If you modify get_or_connect, never insert an await or removal between the readiness check and get_mut.","File the occurrence with logs — it should be impossible under the exclusive borrow."],"tags":["mcp","invariant","internal","unreachable"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}