seanmonstar/reqwest · critical
Client::new()
Error message
Client::new()
What it means
Client::new() (src/async_impl/client.rs:2523-2525) calls ClientBuilder::new().build().expect("Client::new()"). ClientBuilder::build() returns crate::Result<Client> and fails if a TLS backend cannot be initialized, the DNS resolver cannot load system configuration, a config error was recorded on the builder, or (with rustls-no-provider) no crypto provider was installed (see the panic at client.rs:2500-2507 for context). Because new() uses .expect(), any such failure aborts the process with the panic message 'Client::new()'. The doc comment on new() explicitly warns of this and points to Client::builder() for fallible construction.
Source
Thrown at src/async_impl/client.rs:2524
See https://docs.rs/rustls/latest/rustls/#cryptography-providers for details."
);
#[cfg(feature = "__rustls-aws-lc-rs")]
Arc::new(rustls::crypto::aws_lc_rs::default_provider())
}
impl Client {
/// Constructs a new `Client`.
///
/// # Panics
///
/// This method panics if a TLS backend cannot be initialized, or the resolver
/// cannot load the system configuration.
///
/// Use `Client::builder()` if you wish to handle the failure as an `Error`
/// instead of panicking.
pub fn new() -> Client {
ClientBuilder::new().build().expect("Client::new()")
}
/// Creates a `ClientBuilder` to configure a `Client`.
///
/// This is the same as `ClientBuilder::new()`.
pub fn builder() -> ClientBuilder {
ClientBuilder::new()
}
/// Convenience method to make a `GET` request to a URL.
///
/// # Errors
///
/// This method fails whenever the supplied `Url` cannot be parsed.
pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
self.request(Method::GET, url)
}
View on GitHub (pinned to 9f06fd28ab)
Solutions
- Replace Client::new() with Client::builder().build()? so failures return a Result instead of panicking, and handle the error.
- Install ca-certificates in the container (apt-get install ca-certificates / apk add ca-certificates) or bundle roots via .add_root_certificate().
- If using rustls-no-provider, install a provider before building: rustls::crypto::aws_lc_rs::default_provider().install_default().unwrap();
- For missing resolv.conf, mount /etc/resolv.conf in the container or supply a custom resolver via .dns_resolver().
Example fix
// before
let client = reqwest::Client::new();
// after
let client = match reqwest::Client::builder().build() {
Ok(c) => c,
Err(e) => {
eprintln!("failed to build reqwest client: {e}");
std::process::exit(1);
}
}; Defensive patterns
Strategy: try-catch
Validate before calling
// There is no fallible validation before build(); the fix is to use the fallible builder.
// Pre-flight: ensure a crypto provider is installed when rustls-no-provider is on.
#[cfg(feature = "rustls-no-provider")]
fn ensure_crypto_provider() {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
} Try / catch
// never use Client::new(); always:
let client = match reqwest::Client::builder().build() {
Ok(c) => c,
Err(e) => {
eprintln!("reqwest client build failed: {e}");
// degrade gracefully or exit
std::process::exit(1);
}
}; Prevention
- Never call Client::new() in production paths; prefer Client::builder().build()? so TLS/resolver failures are Result-returned, not panics.
- In Docker, install ca-certificates and ensure /etc/resolv.conf is present before the binary starts.
- With rustls-no-provider, call CryptoProvider::install_default() once at process startup.
- Add a startup smoke test that builds the client and logs a clear error instead of letting the panic surface mid-request.
When it happens
Trigger: Calling Client::new() on a system with missing/broken root certificate stores (e.g. minimal containers without ca-certificates). Building with the 'rustls-no-provider' feature and forgetting to install a CryptoProvider before Client::new(). A GaiResolver failing to load /etc/resolv.conf or a hickory-dns resolver failing its config. Setting an invalid TLS config on the builder that surfaces as config.error inside build() (client.rs:412-414).
Common situations: Alpine / distroless / scratch Docker images without ca-certificates installed. Switching from default native-tls to rustls with the no-provider feature to reduce binary size and forgetting the install_default() call. Sandboxed environments where /etc/resolv.conf is absent. CI runners with restricted system config.
Related errors
AI-assisted analysis of seanmonstar/reqwest@9f06fd28ab (2026-08-10).
Data as JSON: /api/errors/f5a52a839d885ba9.
Report an issue: GitHub.