Hmbown/CodeWhale · error · anyhow::Error
MCP connection disappeared for {server_name}
Error message
MCP connection disappeared for {server_name} What it means
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.
Source
Thrown at crates/tui/src/mcp.rs:2657
.and_then(|config| config.reviewed_plugin.clone())
});
if let Some(source) = plugin_source
&& let Err(error) = source.validate_before_use(server_name, "use")
{
self.drop_connection(server_name, "plugin authority revoked or changed");
return Err(error);
}
let is_ready = self
.connections
.get(server_name)
.map(|conn| conn.is_ready())
.unwrap_or(false);
if is_ready {
return self
.connections
.get_mut(server_name)
.ok_or_else(|| anyhow::anyhow!("MCP connection disappeared for {server_name}"));
}
self.drop_connection(server_name, "reconnect");
// Check static config first, then dynamic servers
let server_config = self
.config
.servers
.get(server_name)
.cloned()
.or_else(|| self.dynamic_servers.read().get(server_name).cloned())
.ok_or_else(|| anyhow::anyhow!("Failed to find MCP server: {server_name}"))?;
if !server_config.is_enabled() {
anyhow::bail!("Failed to connect MCP server '{server_name}': server is disabled");
}
let mut connection = McpConnection::connect_with_policy(View on GitHub (pinned to 8880682c63)
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.
Defensive patterns
Strategy: validation
Try / catch
// Rust: invariant breach — report, attempt one clean retry
match pool.get_or_connect(name).await {
Err(e) if e.to_string().contains("connection disappeared") => {
tracing::error!("internal invariant broken in McpPool: {e:#}");
pool.get_or_connect(name).await // one retry on a possibly-consistent map
}
o => o,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to store MCP connection for {server_name}
- stdout unavailable
- stderr unavailable
- active plugin registry is missing its pre-dotenv environment
- failed to parse git log output
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/83c218a3242bf721.
Report an issue: GitHub.