{"record":{"id":"15697e837198673b","repo":"Hmbown/CodeWhale","slug":"get-timeout","errorCode":null,"errorMessage":"GET timeout","messagePattern":"GET timeout","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp/http.rs","lineNumber":206,"sourceCode":"        let headers = tokio::select! {\n            biased;\n            _ = cancel.cancelled() => {\n                anyhow::bail!(\"MCP session preflight cancelled after plugin authority changed\")\n            }\n            headers = transport.auth.resolved_headers() => headers?,\n        };\n        let request = apply_safe_custom_headers(\n            with_default_mcp_http_headers(transport.client.get(&transport.url), false),\n            &headers,\n        );\n        let response = tokio::select! {\n            biased;\n            _ = cancel.cancelled() => {\n                anyhow::bail!(\"MCP session preflight cancelled after plugin authority changed\")\n            }\n            response = tokio::time::timeout(Duration::from_secs(5), request.send()) => {\n                response\n                    .map_err(|_| anyhow::anyhow!(\"GET timeout\"))?\n                    .map_err(|e| anyhow::anyhow!(\"GET error: {e}\"))?\n            }\n        };\n\n        // Capture session ID from the GET response so subsequent POSTs\n        // (including `initialize`) can include it. This is the same\n        // header-reading logic that would be hit inside\n        // `StreamableHttpTransport::send` for POST responses, but since\n        // the GET is sent before any POST we do it here directly.\n        if let Some(sid) = response\n            .headers()\n            .get(\"Mcp-Session-Id\")\n            .and_then(|v| v.to_str().ok())\n            && transport.session_id.as_deref() != Some(sid)\n        {\n            let session_ref = crate::utils::redacted_identifier_for_log(sid);\n            tracing::debug!(target: \"mcp\", session = %session_ref, \"captured MCP session ID via GET preflight\");\n            transport.session_id = Some(sid.to_string());","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp/http.rs#L188-L224","documentation":"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.","triggerScenarios":"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.","commonSituations":"npx downloading packages on first start; corporate proxies adding latency; a server behind a slow tunnel; an endpoint that hangs instead of answering.","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"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Cheap reachability probe before connecting a streamable HTTP server:\nlet probe = reqwest::Client::new().get(&url).send().await;\nanyhow::ensure!(probe.is_ok_and(|r| r.status().as_u16() < 500), \"server not answering promptly: {url}\");","typeGuard":null,"tryCatchPattern":"match transport.try_establish_session().await {\n    Err(e) if e.to_string().contains(\"GET timeout\") => {\n        // back off briefly and retry once; a cold-starting server often answers on the second attempt\n    }\n    other => other,\n}","preventionTips":["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"],"tags":["mcp","network","timeout","http"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}