{"record":{"id":"6d3c7b15d95b5331","repo":"Y2Z/monolith","slug":"failed-to-initialize-http-client","errorCode":null,"errorMessage":"Failed to initialize HTTP client","messagePattern":"Failed to initialize HTTP client","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/session.rs","lineNumber":47,"sourceCode":"        let mut header_map = HeaderMap::new();\n        if let Some(user_agent) = &options.user_agent {\n            header_map.insert(\n                USER_AGENT,\n                HeaderValue::from_str(user_agent).expect(\"Invalid User-Agent header specified\"),\n            );\n        }\n        let client = Client::builder()\n            .timeout(Duration::from_secs(if options.timeout > 0 {\n                options.timeout\n            } else {\n                // We have to specify something that eventually makes the program fail\n                // (prevent it from hanging forever)\n                600 // 10 minutes in seconds\n            }))\n            .danger_accept_invalid_certs(options.insecure)\n            .default_headers(header_map)\n            .build()\n            .expect(\"Failed to initialize HTTP client\");\n\n        Session {\n            cache,\n            cookies,\n            client,\n            options,\n            urls: Vec::new(),\n        }\n    }\n\n    pub fn retrieve_asset(\n        &mut self,\n        parent_url: &Url,\n        url: &Url,\n    ) -> Result<(Vec<u8>, Url, String, String), reqwest::Error> {\n        let cache_key: String = clean_url(url.clone()).as_str().to_string();\n\n        if !self.urls.contains(&url.as_str().to_string()) {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/Y2Z/monolith/blob/a6fc8d009514b2ea271dda2539f19a1f479ebfab/src/session.rs#L29-L65","documentation":"Session::new builds a reqwest blocking HTTP client and calls .expect(\"Failed to initialize HTTP client\") on Client::builder().build(), which panics if reqwest cannot construct the client. Build failures are almost always caused by an invalid default header value (e.g. a User-Agent containing non-visible-ASCII characters) or TLS backend initialization problems. Because the constructor returns Self rather than a Result, the panic aborts the process instead of returning an error.","triggerScenarios":"Calling Session::new with MonolithOptions whose user_agent contains characters invalid for an HTTP header value (non-ASCII/control chars, or an empty None-checked value that fails HeaderValue::from_str is separately panicked earlier); or the reqwest TLS backend fails to initialize (missing/mismatched native-tls or rustls setup at build time).","commonSituations":"Passing a User-Agent string copied from somewhere containing non-Latin1 characters (emoji, CJK) or control characters; linking reqwest with default-tls/native-tls features on a system without an OpenSSL runtime; embedding the library in an environment where TLS init fails.","solutions":["Sanitize or replace the user_agent option so it contains only visible ASCII characters before calling Session::new","Check that the reqwest TLS feature (default-tls/native-tls or rustls-tls) matches the target platform and its TLS runtime is available","If embedding the library, patch/vendor the constructor to return Result<Self, reqwest::Error> and propagate the build error instead of expect()","Call reqwest::blocking::Client::builder().build() in a smoke test to confirm the failure is in client construction, not Session::new itself"],"exampleFix":"// before\nlet user_agent = options.user_agent.clone().unwrap_or_default();\nSession::new(None, None, options_with(user_agent));\n// after\nlet user_agent = options.user_agent.clone().unwrap_or_default();\nassert!(user_agent.is_ascii() && !user_agent.chars().any(|c| c.is_control()), \"user-agent must be visible ASCII\");\nSession::new(None, None, options_with(user_agent));","handlingStrategy":"validation","validationCode":"fn validate_user_agent(ua: &Option<String>) -> Result<(), String> {\n    match ua {\n        Some(s) if s.is_ascii() && !s.chars().any(|c| c.is_control()) && !s.is_empty() => Ok(()),\n        Some(s) => Err(format!(\"invalid user-agent header value: {:?}\", s)),\n        None => Ok(()),\n    }\n}","typeGuard":"fn is_valid_header_value(v: &str) -> bool {\n    v.is_ascii() && v.bytes().all(|b| (32..=126).contains(&b) || b == b'\\t')\n}","tryCatchPattern":null,"preventionTips":["Keep user-agent strings to printable ASCII only","Run a client-build smoke test in CI for cross-platform targets","Prefer constructors returning Result over expect()-panicking APIs when embedding the library"],"tags":["rust","panic","http-client","tls","reqwest"],"backgroundTag":"http-client-init-panic","analyzedSha":"a6fc8d009514b2ea271dda2539f19a1f479ebfab","analyzedAt":"2026-09-05T20:13:04.517Z","contentChangedAt":"2026-09-05T20:13:04.517Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}