{"record":{"id":"184a4b72bf41434d","repo":"RightNow-AI/openfang","slug":"failed-to-build-http-client-184a4b","errorCode":null,"errorMessage":"Failed to build HTTP client","messagePattern":"Failed to build HTTP client","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/openfang-runtime/src/drivers/copilot.rs","lineNumber":482,"sourceCode":"/// completions through the Copilot API (OpenAI-compatible).\npub struct CopilotDriver {\n    openfang_dir: PathBuf,\n    http_client: reqwest::Client,\n\n    /// Persisted OAuth tokens (ghu_ + grt_).\n    oauth_tokens: Mutex<Option<PersistedTokens>>,\n    /// Cached short-lived Copilot API token.\n    copilot_token: Mutex<Option<CachedCopilotToken>>,\n    /// Cached model list.\n    models: Mutex<Option<CachedModels>>,\n}\n\nimpl CopilotDriver {\n    pub fn new(openfang_dir: PathBuf) -> Self {\n        let http_client = reqwest::Client::builder()\n            .timeout(TOKEN_EXCHANGE_TIMEOUT)\n            .build()\n            .expect(\"Failed to build HTTP client\");\n\n        // Try to load persisted tokens on construction.\n        let persisted = PersistedTokens::load(&openfang_dir);\n        if persisted.is_some() {\n            debug!(\"Loaded persisted Copilot OAuth tokens\");\n        }\n\n        Self {\n            openfang_dir,\n            http_client,\n            oauth_tokens: Mutex::new(persisted),\n            copilot_token: Mutex::new(None),\n            models: Mutex::new(None),\n        }\n    }\n\n    /// Ensure we have a valid `ghu_` access token, refreshing or re-authing as needed.\n    async fn ensure_access_token(&self) -> Result<String, crate::llm_driver::LlmError> {","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-runtime/src/drivers/copilot.rs#L464-L500","documentation":"This panic comes from `reqwest::Client::builder().timeout(TOKEN_EXCHANGE_TIMEOUT).build().expect(...)` in CopilotDriver::new (crates/openfang-runtime/src/drivers/copilot.rs:482). reqwest builds a connection pool with a TLS backend at Client construction; builder().build() returns Err if TLS cannot be initialized, the native certificate store cannot be loaded, or the configuration (timeouts, proxies from env) is invalid. The driver builds the client eagerly because all GitHub Copilot token-exchange calls need it.","triggerScenarios":"(1) rustls-native-certs cannot read the system trust store; (2) native-tls/openssl backend fails to initialize (missing OpenSSL libs, FIPS config problems); (3) an invalid value passed to the builder (e.g. a zero or malformed timeout) — with plain .timeout(Duration) this is usually valid, so TLS init is the realistic cause.","commonSituations":"Minimal/Docker images without CA certificates (/etc/ssl/certs empty); statically-linked binaries built with a mismatched TLS feature set (switching between native-tls and rustls); broken SSL_CERT_FILE/SSL_CERT_DIR env vars; corrupted curl/openssl system config on Linux.","solutions":["Install/repair system CA certificates (apt install ca-certificates / update-ca-certificates).","Pin a single TLS strategy: use reqwest with the rustls-tls feature and default-features = false for portable static builds.","Check SSL_CERT_FILE/SSL_CERT_DIR and proxy env vars (HTTP_PROXY/HTTPS_PROXY) for invalid values that break client construction.","Replace expect with a Result-returning constructor so CopilotDriver::new can report the reqwest error instead of panicking.","Alternatively build the Client lazily via OnceCell and cache it, retrying construction on failure."],"exampleFix":"// before\nlet http_client = reqwest::Client::builder()\n    .timeout(TOKEN_EXCHANGE_TIMEOUT)\n    .build()\n    .expect(\"Failed to build HTTP client\");\n// after\nlet http_client = reqwest::Client::builder()\n    .timeout(TOKEN_EXCHANGE_TIMEOUT)\n    .build()\n    .map_err(|e| DriverError::HttpClientInit(e.to_string()))?;","handlingStrategy":"try-catch","validationCode":"// Check TLS prerequisites before constructing the client (Linux)\nif !std::path::Path::new(\"/etc/ssl/certs\").exists()\n    && std::env::var(\"SSL_CERT_FILE\").is_err()\n{\n    eprintln!(\"no system CA certificates found; reqwest TLS init will fail\");\n}","typeGuard":null,"tryCatchPattern":"let client = reqwest::Client::builder().timeout(TOKEN_EXCHANGE_TIMEOUT).build();\nlet http_client = match client {\n    Ok(c) => c,\n    Err(e) => {\n        log::error!(\"reqwest client init failed: {e}\");\n        return Err(DriverError::HttpClientInit(e.to_string()));\n    }\n};","preventionTips":["Ship/require ca-certificates in Docker images and minimal deployments.","Use reqwest rustls-tls (default-features = false, features = [\"rustls-tls\"]) for deterministic cross-platform TLS.","Do not set invalid SSL_CERT_FILE/SSL_CERT_DIR or proxy env values in the launch environment.","Return Result from driver constructors instead of expect-ing; build the client once and reuse it."],"tags":["rust","reqwest","http","tls","configuration"],"backgroundTag":"reqwest-client-build-failed","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}