Hmbown/CodeWhale · error · anyhow::Error
{backoff.last_error}
Error message
{backoff.last_error} What it means
Rather than a fixed message, this error replays the recorded last_error from a connection's exponential backoff state. When a server is in its backoff window (a prior connect attempt failed and retry_after has not elapsed), any re-connect attempt immediately fails with the original diagnosis so the status row keeps showing why the server is down.
Solutions
- Wait until backoff.retry_after elapses, then the connect is attempted for real and this replay stops
- Fix the underlying cause recorded in backoff.last_error (check the original message for the real failure)
- Restart the session or remove the server from config if it should no longer be connected
Defensive patterns
Strategy: retry
Validate before calling
// check backoff state before attempting a connect
if let Some(b) = pool.connect_backoff.get(&name) {
if std::time::Instant::now() < b.retry_after { return Err(anyhow!(b.last_error.clone())); }
} Try / catch
match result {
Err(e) if std::time::Instant::now() < backoff.retry_after => schedule_retry(backoff.retry_after - Instant::now()),
other => other,
} Prevention
- Surface backoff.retry_after in the UI so users know when the next attempt happens
- Fix the root cause in last_error rather than retrying blindly
- Use exponential backoff with jitter to avoid retry storms
When it happens
Trigger: Calling the pool's connect/refresh pass for a server whose name is in connect_backoff and whose backoff.retry_after is still in the future.
Common situations: A required MCP server crashed on startup (bad command, auth failure) and the UI re-checks status before the backoff timer expires; automated polling of server status during repeated failures.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- MCP catalog changed after tool resolution; retry the call
- MCP session expired
- A managed, project or plugin connector already uses this…
- Absolute path should not warn
- active plugin registry is missing its pre-dotenv…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/157acdd3a5a9db8b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp.rs:3642
continue;
}
// Authority validated immediately above for this same source.
if self
.connections
.get(&name)
.is_some_and(McpConnection::is_transport_ready)
{
continue;
}
// Inside its cooldown a failed server costs nothing and still
// tells the truth: the recorded diagnosis is replayed so the row
// keeps reading `error`, rather than going quiet and looking
// healthy because nobody asked.
if let Some(backoff) = self.connect_backoff.get(&name)
&& std::time::Instant::now() < backoff.retry_after
{
errors.push((name, anyhow::anyhow!(backoff.last_error.clone())));
continue;
}
if self.connecting.contains(&name) {
// An earlier pass spawned this connect and it has not
// resolved; a second pass must not spawn a duplicate.
continue;
}
self.drop_connection(&name, "reconnect");
self.connecting.insert(name.clone());
pending.push((name, server_config));
}
(pending, errors)
}
/// Start connects for servers an explicit tool selection named. Unlike a
/// boot pass the selection is the intent — cooldowns do not apply — but
/// servers already ready or already in flight are left alone, and plugin
/// authority is re-validated exactly as inView on GitHub (pinned to 73e0f67d83)