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

  1. Check reachability and latency to the server URL (curl -m 5 against the endpoint)
  2. Pre-warm slow servers (populate the npx/package cache, keep a container alive) so the first GET answers quickly
  3. Fix the network path (proxy, DNS, tunnel) between codewhale and the server
  4. 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

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

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/15697e837198673b. Report an issue: GitHub.