{"record":{"id":"a420fe4b22ea6d9c","repo":"xai-org/grok-build","slug":"failed-to-build-shared-upload-http-client","errorCode":null,"errorMessage":"failed to build shared upload HTTP client","messagePattern":"failed to build shared upload HTTP client","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-http/src/lib.rs","lineNumber":337,"sourceCode":"/// Without pool eviction, all retries would reuse the same dead connection and fail.\n///\n/// Settings:\n/// - HTTP/1.1 only: a degraded multiplexed HTTP/2 connection can silently drop multipart request bodies.\n///   The drops cascade into 400 errors across all concurrent uploads\n/// - Small connection pool (2 per host) for parallel chunk uploads\n/// - Short idle timeout (10s) to evict stale connections before backoff completes\npub fn shared_upload_client() -> reqwest::Client {\n    static UPLOAD_CLIENT: OnceLock<reqwest::Client> = OnceLock::new();\n    UPLOAD_CLIENT\n        .get_or_init(|| {\n            xai_grok_extra_ca::build_reqwest_client(|builder| {\n                builder\n                    .http1_only()\n                    .pool_max_idle_per_host(2)\n                    .pool_idle_timeout(std::time::Duration::from_secs(10))\n                    .user_agent(process_user_agent_string())\n            })\n            .expect(\"failed to build shared upload HTTP client\")\n        })\n        .clone()\n}\n\n/// A fresh, pool-less HTTP/1.1 [`reqwest::Client`], deliberately not cached: each request opens a new connection.\n/// There is no connect timeout; callers bound each request with their own total timeout.\n/// The retry policy that uses this client to escape a poisoned pool lives on `send_with_retry_escaping_pool`.\n/// The build can fail under file-descriptor or TLS pressure; the caller must not panic on error (the fallback lives at the call site).\npub(crate) fn fresh_http1_client() -> reqwest::Result<reqwest::Client> {\n    xai_grok_extra_ca::build_reqwest_client(|builder| {\n        builder\n            .http1_only()\n            .pool_max_idle_per_host(0)\n            .user_agent(process_user_agent_string())\n    })\n}\n\n/// Joins an error's `source()` chain into one string.","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-http/src/lib.rs#L319-L355","documentation":"shared_upload_client lazily builds a cached, HTTP/1.1-only reqwest blocking client tuned for uploads (small pool, short idle timeout, User-Agent set) and .expect()s the build succeeds. Panics indicate the reqwest/TLS stack could not construct the client.","triggerScenarios":"First call to shared_upload_client() when the crypto provider cannot initialize, CA material fails to load, process_user_agent_string() yields a configuration reqwest rejects, or the builder options are invalid in this build.","commonSituations":"Same environment issues as other shared clients: mismatched rustls features, stripped containers, conflicting global crypto provider; also an invalid user-agent string from env-derived origin info.","solutions":["Align rustls/aws-lc-rs feature flags workspace-wide and rebuild","Validate the env-derived client info (origin_client_info_from_env) that feeds process_user_agent_string()","Pre-warm the upload client during startup so failures surface with full context, not deep in an upload path","Pass a prebuilt client where the API allows instead of relying on the shared initializer"],"exampleFix":"// before\nlet client = shared_upload_client(); // first call may panic\n// after\n// at startup\nlet _ = shared_upload_client(); // fail fast with clear context\n// later in upload path\nlet client = shared_upload_client();","handlingStrategy":"try-catch","validationCode":"let client = std::panic::catch_unwind(xai_grok_http::shared_upload_client)\n    .map_err(|_| anyhow!(\"shared upload client build failed (TLS init?)\"))?;","typeGuard":"null","tryCatchPattern":"std::panic::catch_unwind(|| {\n    let c = shared_upload_client();\n    c.post(url).body(body).send()\n})\n.map_err(|_| anyhow!(\"upload HTTP stack unavailable\"))?","preventionTips":["Pre-warm the upload client during startup","Validate env-derived origin/client info that feeds the User-Agent","Keep rustls/aws-lc-rs features consistent; rebuild on version bumps"],"tags":["http","tls","upload","panics","reqwest","rust"],"backgroundTag":"tls-client-build-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}