{"record":{"id":"9ba13b6f74ae4b9b","repo":"getzola/zola","slug":"reqwest-client-build","errorCode":null,"errorMessage":"reqwest client build","messagePattern":"reqwest client build","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"components/link_checker/src/lib.rs","lineNumber":38,"sourceCode":"    }\n}\n\npub fn message(res: &Result) -> String {\n    match res {\n        Ok(code) => code.to_string(),\n        Err(error) => error.clone(),\n    }\n}\n\n// Keep history of link checks so a rebuild doesn't have to check again\nstatic LINKS: LazyLock<Arc<RwLock<HashMap<String, Result>>>> =\n    LazyLock::new(|| Arc::new(RwLock::new(HashMap::new())));\n// Make sure to create only a single Client so that we can reuse the connections\nstatic CLIENT: LazyLock<Client> = LazyLock::new(|| {\n    Client::builder()\n        .user_agent(concat!(env!(\"CARGO_PKG_NAME\"), \"/\", env!(\"CARGO_PKG_VERSION\")))\n        .build()\n        .expect(\"reqwest client build\")\n});\n\npub fn check_url(url: &str, config: &LinkChecker) -> Result {\n    {\n        let guard = LINKS.read().unwrap();\n        if let Some(res) = guard.get(url) {\n            return res.clone();\n        }\n    }\n\n    let mut headers = HeaderMap::new();\n    headers.insert(ACCEPT, \"text/html\".parse().unwrap());\n    headers.append(ACCEPT, \"*/*\".parse().unwrap());\n\n    // TODO: pass the client to the check_url, do not pass the config\n\n    let check_anchor = !config.skip_anchor_prefixes.iter().any(|prefix| url.starts_with(prefix));\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/components/link_checker/src/lib.rs#L20-L56","documentation":"The link_checker component builds a shared reqwest::blocking::Client once (LazyLock) so connections are reused, and panics via .expect(\"reqwest client build\") if the client cannot be constructed. reqwest fails Client::builder().build() only when the TLS backend cannot be initialized.","triggerScenarios":"First call to check_url (which triggers the CLIENT LazyLock) when reqwest's TLS backend fails to initialize — typically missing/broken native TLS or OpenSSL setup, or a mismatched feature set (rustls vs native-tls) at build time.","commonSituations":"Deploying to a slim Docker image without OpenSSL/ca-certificates; cross-compiling with an incompatible TLS feature; a distro whose OpenSSL version is incompatible with the compiled crate.","solutions":["Install the TLS runtime prerequisites on the target machine (e.g. libssl, ca-certificates packages).","Build reqwest with the rustls-tls feature to avoid native OpenSSL dependence.","Rebuild/reinstall the binary for the target platform with matching TLS features.","Verify with a minimal reqwest build/run on the same host to isolate the TLS init failure."],"exampleFix":"// before (Cargo.toml)\nreqwest = { version = \"0.12\", features = [\"blocking\"] }\n// after\nreqwest = { version = \"0.12\", features = [\"blocking\", \"rustls-tls\"], default-features = false }","handlingStrategy":"fallback","validationCode":"// Check TLS prerequisites before first network call\nstd::process::Command::new(\"ldconfig\").args([\"-p\"]).output()\n    .map(|o| String::from_utf8_lossy(&o.stdout).contains(\"libssl\"))\n    .unwrap_or(false); // also verify /etc/ssl/certs exists","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build with rustls-tls to remove the OpenSSL runtime dependency.","Install ca-certificates and libssl in deployment images.","Smoke-test a network request at startup to fail fast.","Keep reqwest features consistent across the workspace."],"tags":["reqwest","tls","http-client","startup-panic"],"backgroundTag":"tls-backend-init-failed","analyzedSha":"61d30828217957120309db657950224edf9707e2","analyzedAt":"2026-09-03T14:39:09.727Z","contentChangedAt":"2026-09-03T14:39:09.727Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}