Hmbown/CodeWhale · error
Failed to call MCP method
Error message
Failed to call MCP method '{}': connection '{}' is not ready What it means
Requests can only be sent to an MCP connection whose state is ConnectionState::Ready (initialization handshake completed). Calling a method on a connection still connecting, failed, or already torn down bails with this error naming the method and connection. It is a state-machine guard, not a network failure.
Solutions
- Ensure the MCP server finished initializing before issuing calls (await the ready signal)
- Reconnect/restart the MCP server if its state left Ready
- Check the server's stderr/logs for a crash that moved the connection out of Ready
- Increase startup timeout or reduce server cold-start time (e.g. pre-install npx packages)
Defensive patterns
Strategy: type-guard
Validate before calling
// only issue calls after the ready signal
connection.ready().await?; // awaits ConnectionState::Ready
let value = connection.call("tools/call", params, timeout).await?; Type guard
fn is_ready(c: &McpConnection) -> bool { c.state() == ConnectionState::Ready } Try / catch
match conn.call(method, params, timeout).await {
Err(e) if e.to_string().contains("is not ready") => {
conn.reconnect().await?; // then retry once
conn.call(method, params, timeout).await
}
other => other,
} Prevention
- Always await readiness before first call
- Watch server logs for crashes that flip state
- Handle slow cold starts (npx downloads) with generous init timeouts
When it happens
Trigger: Calling any MCP method (tools/call, tools/list, ping, etc.) before initialization completes, after a connection error transitioned state away from Ready, or after the transport was shut down/cancelled.
Common situations: A race where a tool invocation fires while the server is still starting (slow npx/npm cold start); the server crashed earlier and the stale connection object is reused; shutdown/cancel racing a pending call.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Failed to store MCP connection for
- MCP configuration changed while connecting
- MCP connection disappeared for
- A managed, project or plugin connector already uses this…
- Absolute path should not warn
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/39a4ad7f74cfeb70.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp.rs:2254
"prompts/get",
serde_json::json!({
"name": prompt_name,
"arguments": arguments
}),
timeout_secs,
)
.await
}
/// Generic method to call an MCP method
async fn call_method(
&mut self,
method: &str,
params: serde_json::Value,
timeout_secs: u64,
) -> Result<serde_json::Value> {
if self.state != ConnectionState::Ready {
anyhow::bail!(
"Failed to call MCP method '{}': connection '{}' is not ready",
method,
self.name
);
}
if let Some(source) = self.config.reviewed_plugin.as_ref() {
source.validate_before_use(&self.name, method)?;
}
let call_id = self.next_id();
if let Err(error) = self
.send(serde_json::json!({
"jsonrpc": "2.0",
"id": &call_id,
"method": method,
"params": params
}))
.awaitView on GitHub (pinned to 73e0f67d83)