seanmonstar/reqwest · critical
Client::new()
Error message
Client::new()
What it means
blocking::Client::new() (src/blocking/client.rs:1277-1279) mirrors the async Client::new(): it calls ClientBuilder::new().build().expect("Client::new()"), so any ClientBuilder failure (TLS backend init, system DNS config load, rustls crypto provider missing) panics the process. Additionally, the blocking client wraps an async runtime internally; the doc comment at client.rs:1275-1276 notes that calling blocking::Client methods from inside an async runtime context also panics. The same expect string 'Client::new()' is shared by both clients, so the panic site must be distinguished by which Client you constructed.
Source
Thrown at src/blocking/client.rs:1278
Self::new()
}
}
impl Client {
/// Constructs a new `Client`.
///
/// # Panic
///
/// This method panics if 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.
///
/// This method also panics if called from within an async runtime. See docs
/// on [`reqwest::blocking`][crate::blocking] for details.
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 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
- Do not call any blocking client method from within an async runtime; switch to reqwest::Client (async) inside async contexts.
- Replace blocking::Client::new() with reqwest::blocking::Client::builder().build()? to surface failures as a Result instead of a panic.
- Install ca-certificates / provide root certs and ensure /etc/resolv.conf is present in the deployment.
- With rustls-no-provider, call rustls::crypto::aws_lc_rs::default_provider().install_default().unwrap() before constructing the blocking client.
Example fix
// before: panics inside a tokio runtime
#[tokio::main]
async fn main() {
let resp = reqwest::blocking::get("https://example.com").unwrap();
}
// after: use the async client inside an async runtime
#[tokio::main]
async fn main() {
let resp = reqwest::get("https://example.com").await.unwrap();
} Defensive patterns
Strategy: try-catch
Validate before calling
// No pre-flight check exists; use the fallible builder and keep blocking calls out of async runtimes.
#[cfg(feature = "rustls-no-provider")]
fn ensure_crypto_provider() {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
} Try / catch
// 1) build fallibly
let client = match reqwest::blocking::Client::builder().build() {
Ok(c) => c,
Err(e) => { eprintln!("client build failed: {e}"); std::process::exit(1); }
};
// 2) never call blocking client methods from inside #[tokio::main]/async fn;
// use reqwest::Client (async) there instead. Prevention
- Never call reqwest::blocking::* from within an async runtime; use the async reqwest::Client inside async code.
- Use reqwest::blocking::Client::builder().build()? instead of ::new() to avoid panics on TLS/resolver failure.
- Install ca-certificates and ensure /etc/resolv.conf exist in the deployment image.
- If using rustls-no-provider, install the crypto provider at startup before any blocking::Client::builder().
When it happens
Trigger: Calling reqwest::blocking::Client::new() in a process whose TLS/resolver setup is broken (same set as the async client). Calling reqwest::blocking::get() or any blocking client method from within a tokio / async-std runtime context, because the blocking client spawns its own runtime and panics if one is already present. Using rustls-no-provider without installing a CryptoProvider before the blocking Client::new().
Common situations: Calling reqwest::blocking from inside a #[tokio::main] or #[actix_web::main] handler. Mixing a blocking::Client with an async codebase during migration. Minimal containers missing ca-certificates or /etc/resolv.conf. Forgetting the crypto provider install when the no-provider feature is on.
Related errors
AI-assisted analysis of seanmonstar/reqwest@9f06fd28ab (2026-08-10).
Data as JSON: /api/errors/e0793d1153aef2d6.
Report an issue: GitHub.