Hmbown/CodeWhale · error
GET timeout
Error message
GET timeout
What it means
The streamable-HTTP session preflight issues a GET to the server endpoint wrapped in a 5-second tokio::time::timeout purely to bound connection establishment. If the GET does not complete within those 5 seconds, the preflight aborts with 'GET timeout' and the connection attempt fails.
Source
Thrown at crates/tui/src/mcp/http.rs:206
let headers = tokio::select! {
biased;
_ = cancel.cancelled() => {
anyhow::bail!("MCP session preflight cancelled after plugin authority changed")
}
headers = transport.auth.resolved_headers() => headers?,
};
let request = apply_safe_custom_headers(
with_default_mcp_http_headers(transport.client.get(&transport.url), false),
&headers,
);
let response = tokio::select! {
biased;
_ = cancel.cancelled() => {
anyhow::bail!("MCP session preflight cancelled after plugin authority changed")
}
response = tokio::time::timeout(Duration::from_secs(5), request.send()) => {
response
.map_err(|_| anyhow::anyhow!("GET timeout"))?
.map_err(|e| anyhow::anyhow!("GET error: {e}"))?
}
};
// Capture session ID from the GET response so subsequent POSTs
// (including `initialize`) can include it. This is the same
// header-reading logic that would be hit inside
// `StreamableHttpTransport::send` for POST responses, but since
// the GET is sent before any POST we do it here directly.
if let Some(sid) = response
.headers()
.get("Mcp-Session-Id")
.and_then(|v| v.to_str().ok())
&& transport.session_id.as_deref() != Some(sid)
{
let session_ref = crate::utils::redacted_identifier_for_log(sid);
tracing::debug!(target: "mcp", session = %session_ref, "captured MCP session ID via GET preflight");
transport.session_id = Some(sid.to_string());View on GitHub (pinned to 8880682c63)
Solutions
- Check reachability and latency to the server URL (curl -m 5 against the endpoint)
- Pre-warm slow servers (populate the npx/package cache, keep a container alive) so the first GET answers quickly
- Fix the network path (proxy, DNS, tunnel) between codewhale and the server
- Retry the connection - transient slowness often clears
Defensive patterns
Strategy: retry
Validate before calling
// Cheap reachability probe before connecting a streamable HTTP server:
let probe = reqwest::Client::new().get(&url).send().await;
anyhow::ensure!(probe.is_ok_and(|r| r.status().as_u16() < 500), "server not answering promptly: {url}"); Try / catch
match transport.try_establish_session().await {
Err(e) if e.to_string().contains("GET timeout") => {
// back off briefly and retry once; a cold-starting server often answers on the second attempt
}
other => other,
} Prevention
- Pre-warm npx/container-based MCP servers so the first GET answers well under 5 seconds
- Keep MCP servers on low-latency paths from the codewhale process (avoid slow tunnels/proxies)
- Probe the endpoint with curl during environment setup to catch hanging servers early
When it happens
Trigger: try_establish_session against a server whose initial GET takes longer than 5 seconds: cold-starting npx-based servers, slow proxies, or high-latency links.
Common situations: npx downloading packages on first start; corporate proxies adding latency; a server behind a slow tunnel; an endpoint that hangs instead of answering.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timed out waiting for MCP JSON-RPC response from server '{}'
- Runtime API request failed (${status}): ${message}
- iLink API ${endpoint} failed: HTTP ${response.status} — ${te
- failed to fetch {description} from {url}: HTTP {status} {bod
- failed to fetch {description} from {url}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/15697e837198673b.
Report an issue: GitHub.