Hmbown/CodeWhale · error · anyhow::Error

MCP connection disappeared for

Error message

MCP connection disappeared for {server_name}

What it means

After checking that a connection reports is_transport_ready, the pool looks it up in self.connections and expects it to still be present. Hitting this error means the ready-check and the map lookup raced: the connection vanished between the two steps. It is an internal invariant violation, not an expected user-facing condition.

Solutions

  1. Retry the operation; the pool will reconnect lazily on the next dispatch.
  2. If reproducible, look for unsynchronized mutation of pool connections while a dispatch is in flight.
  3. Hold the pool lock across the ready-check and lookup, or re-fetch the connection after the probe.
  4. Report it as a bug with a trace if it occurs without concurrent use.
Defensive patterns

Strategy: retry

Validate before calling

// Probe readiness and presence atomically where the API allows
let conn = pool.try_get_ready_connection(server_name); // single lookup instead of check-then-get

Try / catch

match pool.call_tool(server, tool, input) {
    Err(e) if e.to_string().contains("MCP connection disappeared") => {
        // transient race: retry once; pool reconnects lazily
        pool.call_tool(server, tool, input).await?
    }
    other => other?,
}

Prevention

When it happens

Trigger: Concurrent mutation of the pool's connections map (shutdown, reconnect taking the stale connection via .take(), or removal by another task) between the is_ready probe and get_mut(server_name).

Common situations: Reconnect logic racing a concurrent tool dispatch; pool teardown while a request is resolving a connection; dynamic server removal concurrent with a call.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/83c218a3242bf721. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/mcp.rs:3172

        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);
        }

        // Authority was just validated above for this same source; checking
        // it again here would re-hash the bundle within one dispatch (#6209).
        let is_ready = self
            .connections
            .get(server_name)
            .map(McpConnection::is_transport_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}"));
        }

        // Take (don't drop) the stale connection: if the reconnect attempt
        // below fails, the previous connection is restored so its last-good
        // tool catalog stays model-visible during the outage instead of
        // disappearing with a dropped transport (#6187).
        let previous_connection = self.connections.remove(server_name);
        if previous_connection.is_some() {
            tracing::debug!(
                target: "mcp",
                server = %server_name,
                reason = "reconnect",
                "detached MCP connection for reconnect"
            );
        }

        // Check static config first, then dynamic servers
        let server_config = self

View on GitHub (pinned to 73e0f67d83)