{"record":{"id":"76b60041006d4727","repo":"xai-org/grok-build","slug":"failed-to-build-shared-blocking-http-client","errorCode":null,"errorMessage":"failed to build shared blocking HTTP client","messagePattern":"failed to build shared blocking HTTP client","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/codegen/xai-grok-http/src/lib.rs","lineNumber":579,"sourceCode":"///\n/// Mirrors `shared_client()`'s pool self-healing for the same reason: this client is reused (settings, prefetch).\n/// Idle and TCP eviction drops a connection before the upstream idle window (~60-100s; 30s is a conservative default) closes it.\n/// The HTTP/2 keepalive-ping setters that `shared_client()` uses are not exposed on reqwest's blocking `ClientBuilder` (0.12).\n/// Only the idle and TCP eviction half applies here.\npub fn shared_startup_blocking_client() -> reqwest::blocking::Client {\n    static BLOCKING_CLIENT: OnceLock<reqwest::blocking::Client> = OnceLock::new();\n    BLOCKING_CLIENT\n        .get_or_init(|| {\n            let _timer = startup_timer!(\"startup.http_blocking_client_build\");\n            xai_grok_extra_ca::build_blocking_reqwest_client(|builder| {\n                builder\n                    .connect_timeout(STARTUP_FETCH_TIMEOUT)\n                    .timeout(STARTUP_FETCH_TIMEOUT)\n                    .user_agent(process_user_agent_string())\n                    .pool_idle_timeout(std::time::Duration::from_secs(30))\n                    .tcp_keepalive(std::time::Duration::from_secs(30))\n            })\n            .expect(\"failed to build shared blocking HTTP client\")\n        })\n        .clone()\n}\n\n#[allow(clippy::disallowed_methods)] // test clients hit localhost mocks\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    /// `error_cause_chain` appends each `source()` joined with \": \", so a reqwest error whose `Display` hides the hyper cause still surfaces it.\n    #[test]\n    fn error_cause_chain_appends_hidden_sources() {\n        #[derive(Debug)]\n        struct Leaf;\n        impl std::fmt::Display for Leaf {\n            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n                write!(f, \"connection closed before message completed\")\n            }","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-http/src/lib.rs#L561-L597","documentation":"This panic fires when `reqwest::blocking::Client::build()` fails inside `shared_startup_blocking_client`, the lazy initializer for a process-wide blocking HTTP client used at startup. The builder itself validates configuration (TLS backend, timeout values, user-agent), so a failure here means the client could not be constructed at all — typically an TLS/runtime initialization problem, not a network issue. The `.expect` deliberately aborts startup because no HTTP fetches can proceed without this client.","triggerScenarios":"Calling any startup fetch path that lazily initializes the shared client when reqwest's ClientBuilder rejects the configuration — e.g. native-tls/rustls backend initialization failure, invalid timeout resolution, or TLS root store load failure on the host.","commonSituations":"Hosts with a broken or missing system certificate store; statically-linked binaries whose TLS backend cannot load roots; exotic platforms where reqwest's blocking runtime (tokio) cannot be initialized; invalid env-var-driven TLS configuration (e.g. bad SSL_CERT_FILE).","solutions":["Check the panic's inner source message from reqwest — it names the exact build failure (usually TLS backend or root-store load).","On Linux, ensure the CA bundle exists (ca-certificates installed) or set SSL_CERT_FILE to a valid PEM bundle.","If the failure is TLS-root related, try a build with a vendored root store (rustls-tls with webpki-roots) or embed certs.","Verify the binary runs on a supported platform where tokio's blocking runtime can spawn threads (ulimit/thread limits can starve client construction)."],"exampleFix":"// before\n.expect(\"failed to build shared blocking HTTP client\")\n// after\n.map_err(|e| StartupError::HttpClientInit(e.to_string()))?  // or log and fall back to a per-request client","handlingStrategy":"fallback","validationCode":"// preflight: ensure a CA bundle is visible before building the client\nif std::env::var_os(\"SSL_CERT_FILE\").map_or(true, |p| !std::path::Path::new(&p).exists()) {\n    eprintln!(\"warning: SSL_CERT_FILE missing; client build may fail\");\n}","typeGuard":null,"tryCatchPattern":"// Rust: catch_unwind around lazy init, or make the initializer fallible\nlet client = std::panic::catch_unwind(shared_startup_blocking_client)\n    .map_err(|_| StartupError::HttpClientInit)?;","preventionTips":["Ship a vendored root store (rustls + webpki-roots) so builds don't depend on host CA state","Log the inner reqwest builder error, not just the expect message","Smoke-test the binary in minimal containers where cert stores are often absent"],"tags":["rust","http-client","tls","panic","startup"],"backgroundTag":"http-client-build-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}