{"record":{"id":"98db6762f0e9985c","repo":"RightNow-AI/openfang","slug":"failed-to-build-http-client","errorCode":null,"errorMessage":"Failed to build HTTP client","messagePattern":"Failed to build HTTP client","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openfang-cli/src/main.rs","lineNumber":1205,"sourceCode":"\n/// Build an HTTP client for daemon calls.\n///\n/// When api_key is configured in config.toml, the client automatically\n/// includes a `Authorization: Bearer <key>` header on every request.\n/// When api_key is empty or missing, no auth header is sent.\npub(crate) fn daemon_client() -> reqwest::blocking::Client {\n    let mut builder =\n        reqwest::blocking::Client::builder().timeout(std::time::Duration::from_secs(120));\n\n    if let Some(key) = read_api_key() {\n        let mut headers = reqwest::header::HeaderMap::new();\n        if let Ok(val) = reqwest::header::HeaderValue::from_str(&format!(\"Bearer {key}\")) {\n            headers.insert(reqwest::header::AUTHORIZATION, val);\n        }\n        builder = builder.default_headers(headers);\n    }\n\n    builder.build().expect(\"Failed to build HTTP client\")\n}\n\n/// Helper: send a request to the daemon and parse the JSON body.\n/// Exits with error on connection failure.\npub(crate) fn daemon_json(\n    resp: Result<reqwest::blocking::Response, reqwest::Error>,\n) -> serde_json::Value {\n    match resp {\n        Ok(r) => {\n            let status = r.status();\n            let body = r.json::<serde_json::Value>().unwrap_or_default();\n            if status.is_server_error() {\n                ui::error_with_fix(\n                    &format!(\"Daemon returned error ({})\", status),\n                    \"Check daemon logs: ~/.openfang/tui.log\",\n                );\n            }\n            body","sourceCodeStart":1187,"sourceCodeEnd":1223,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-cli/src/main.rs#L1187-L1223","documentation":"reqwest::blocking::Client::builder().build() returns Err when the client cannot be constructed — most often TLS backend initialization failure (rustls/native-tls root store issues) or an invalid configuration on the builder (bad timeout, invalid header). The CLI panics with expect, aborting the process since the daemon HTTP client is essential.","triggerScenarios":"Client::builder()...build() returns Err: invalid default header values inserted (e.g. AUTHORIZATION header built from a key containing non-visible-ASCII characters that slipped past from_str), TLS backend init failure, or system proxy configuration that reqwest cannot parse.","commonSituations":"API key/env var containing newline or non-ASCII bytes used in the Authorization header; corporate proxy env vars (http_proxy/https_proxy) with malformed URLs; missing/incorrectly built TLS root certificates in the container.","solutions":["Validate/sanitize the API key before inserting it (strip non-visible-ASCII, or skip the header on from_str failure — the code does check from_str but verify the key itself).","Inspect proxy env vars (HTTPS_PROXY etc.) for malformed URLs and fix or unset them.","Check TLS backend health: ensure rustls-tls or native-tls feature is compiled in and CA certs are present (SSL_CERT_FILE / ca-certificates).","Replace .expect with error propagation and a user-facing message plus retry with default Client::new()."],"exampleFix":"// before\nbuilder.build().expect(\"Failed to build HTTP client\")\n// after\nbuilder.build().unwrap_or_else(|e| {\n    eprintln!(\"warning: custom client build failed ({e}); using default client\");\n    reqwest::blocking::Client::new()\n})","handlingStrategy":"fallback","validationCode":"// Check environment before building the client\nfn client_env_ok() -> Result<(), String> {\n    for v in [\"HTTPS_PROXY\", \"https_proxy\", \"HTTP_PROXY\", \"http_proxy\"] {\n        if let Ok(p) = std::env::var(v) {\n            if p.parse::<url::Url>().is_err() {\n                return Err(format!(\"{v} is not a valid URL: {p}\"));\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"// match on Result instead of expect\nlet client = match builder.build() {\n    Ok(c) => c,\n    Err(e) => {\n        eprintln!(\"error: cannot build HTTP client: {e}\");\n        std::process::exit(1);\n    }\n};","preventionTips":["Sanitize API keys before inserting as header values (visible ASCII only).","Validate proxy env vars in startup checks.","Ship CA certificates in CLI container images.","Test the CLI in clean environments (no proxy vars, minimal images) in CI."],"tags":["reqwest","http","cli","panic","tls"],"backgroundTag":"http-client-build-failed","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}