getzola/zola · critical
reqwest client build
Error message
reqwest client build
What it means
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.
Source
Thrown at components/link_checker/src/lib.rs:38
}
}
pub fn message(res: &Result) -> String {
match res {
Ok(code) => code.to_string(),
Err(error) => error.clone(),
}
}
// Keep history of link checks so a rebuild doesn't have to check again
static LINKS: LazyLock<Arc<RwLock<HashMap<String, Result>>>> =
LazyLock::new(|| Arc::new(RwLock::new(HashMap::new())));
// Make sure to create only a single Client so that we can reuse the connections
static CLIENT: LazyLock<Client> = LazyLock::new(|| {
Client::builder()
.user_agent(concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")))
.build()
.expect("reqwest client build")
});
pub fn check_url(url: &str, config: &LinkChecker) -> Result {
{
let guard = LINKS.read().unwrap();
if let Some(res) = guard.get(url) {
return res.clone();
}
}
let mut headers = HeaderMap::new();
headers.insert(ACCEPT, "text/html".parse().unwrap());
headers.append(ACCEPT, "*/*".parse().unwrap());
// TODO: pass the client to the check_url, do not pass the config
let check_anchor = !config.skip_anchor_prefixes.iter().any(|prefix| url.starts_with(prefix));
View on GitHub (pinned to 61d3082821)
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.
Example fix
// before (Cargo.toml)
reqwest = { version = "0.12", features = ["blocking"] }
// after
reqwest = { version = "0.12", features = ["blocking", "rustls-tls"], default-features = false } Defensive patterns
Strategy: fallback
Validate before calling
// Check TLS prerequisites before first network call
std::process::Command::new("ldconfig").args(["-p"]).output()
.map(|o| String::from_utf8_lossy(&o.stdout).contains("libssl"))
.unwrap_or(false); // also verify /etc/ssl/certs exists Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of getzola/zola@61d3082821 (2026-09-03).
Data as JSON: /api/errors/9ba13b6f74ae4b9b.
Report an issue: GitHub.