{"record":{"id":"69769347dc1313ab","repo":"Hmbown/CodeWhale","slug":"get-error-e","errorCode":null,"errorMessage":"GET error: {e}","messagePattern":"GET error: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp/http.rs","lineNumber":207,"sourceCode":"            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());\n        }","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/mcp/http.rs#L189-L225","documentation":"The same 5-second-bounded preflight GET failed at the transport level: `request.send()` returned a reqwest error `e` within the budget, which is formatted into \"GET error: {e}\" (crates/tui/src/mcp/http.rs:207). The embedded reqwest error distinguishes the cause — DNS resolution failure, connection refused, TLS error, proxy error, etc. This is a network/request-construction failure, not a timeout (that is error 1056).","triggerScenarios":"Connecting to an HTTP MCP endpoint whose host does not resolve (typo'd hostname), refuses connections (service down / wrong port), presents an invalid/self-signed certificate, requires a client proxy that rejects the request, or redirects improperly. Any `reqwest::Error` from the preflight GET maps here.","commonSituations":"Wrong URL or port in the MCP server config; DNS not resolving internal hostnames (VPN down); self-signed certs in dev environments; endpoint moved or decommissioned; corporate TLS-inspecting proxy breaking the handshake; IPv6-only misconfiguration.","solutions":["Read the embedded `{e}` — 'error trying to connect: dns error' means bad host/VPN, 'Connection refused' means wrong port/service down, TLS errors mean certificate problems.","Verify basic reachability with curl against the same URL; fix the URL/port in the MCP server config if curl also fails.","For self-signed certificates, install the CA locally or serve a publicly-trusted cert (do not disable verification).","Reconnect VPN or fix DNS for internal hostnames; confirm the MCP service is running on the target host."],"exampleFix":"# before\nurl = \"https://mcp.internal.example/mcp\"  # 'GET error: error trying to connect: dns error'\n\n# after — fix host/port from the service's actual binding\nurl = \"https://mcp.internal.example:8443/mcp\"  # curl -v confirms 200 on this URL","handlingStrategy":"try-catch","validationCode":"// Pre-flight the URL the same way before configuring:\nlet url = reqwest::Url::parse(endpoint)?; // catches malformed URLs early\n// curl -v <endpoint> to confirm DNS, port, and TLS all succeed","typeGuard":null,"tryCatchPattern":"match connect_streamable_http(&url, &headers).await {\n    Ok(t) => t,\n    Err(e) if e.to_string().starts_with(\"GET error:\") => {\n        // inspect the embedded reqwest cause: dns -> fix host/VPN; refused -> fix port/service; tls -> fix cert\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Validate endpoint URLs (scheme, host, port) at config-write time, not just at connect time.","Keep DNS/VPN healthy for internal hostnames; prefer stable public hostnames for remote MCP servers.","Use trusted certificates; self-signed certs will fail the preflight."],"tags":["mcp","http","network","reqwest","connection","codewhale"],"backgroundTag":"http-connection-failed","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}