Kuberwastaken/claurst · critical
failed to build reqwest client
Error message
failed to build reqwest client
What it means
This panic comes from an `.expect()` on `reqwest::Client::builder().build()` while constructing an OpenAI-compatible provider. The reqwest client builder only fails when process-wide initialization fails, typically the TLS backend (rustls or native-tls) cannot be initialized. The library treats this as unrecoverable: without an HTTP client no API calls can ever succeed.
Solutions
- Check that the binary links a working TLS backend: verify `openssl`/`libssl` is present (`ldd ./claurst`) or switch Cargo features to rustls (`default-features = false, features = ["rustls-tls"]` on reqwest).
- Add CA certificates to the container image (e.g. `apk add ca-certificates` / `apt-get install ca-certificates`).
- If TLS backend init is expected to fail in embedded contexts, refactor `new` to return `Result<Self, reqwest::Error>` and propagate instead of expecting.
- Test client construction early at startup (`reqwest::Client::new()`) so the failure surfaces with a clear message rather than deep inside provider setup.
Example fix
// before
let http_client = reqwest::Client::builder()
.timeout(crate::request_timeout())
.build()
.expect("failed to build reqwest client");
// after
let http_client = reqwest::Client::builder()
.timeout(crate::request_timeout())
.build()
.map_err(|e| ProviderError::Init(format!("failed to build reqwest client: {e}")))?; Defensive patterns
Strategy: fallback
Validate before calling
// Before constructing the provider, probe client construction:
if let Err(e) = reqwest::Client::new() {
eprintln!("TLS/HTTP client unavailable: {e}");
// fall back to non-TLS transport or abort startup with a clear message
} Try / catch
// This is a panic, not a Result — catch at process boundary if embedding:
let result = std::panic::catch_unwind(|| OpenAiCompatProvider::new("id", "name", "https://api.example.com"));
match result {
Ok(provider) => { /* use provider */ }
Err(_) => { /* degrade: disable API features, report TLS init failure */ }
} Prevention
- Build with the rustls-tls feature to avoid native OpenSSL linkage problems
- Install ca-certificates in all deployment images
- Smoke-test reqwest client construction at application startup, not lazily
- Run `ldd` on release binaries in a container matching the target environment
When it happens
Trigger: Calling `OpenAiCompatProvider::new(id, name, base_url)` in a process where the TLS backend failed to initialize — most commonly `reqwest::Client::builder().timeout(crate::request_timeout()).build()` returning Err because the native TLS library could not be loaded or rustls ring crypto init failed.
Common situations: Deploying to a musl/statically-linked or minimal Docker image missing CA certificates or the native TLS shared library; cross-compiled binaries with a mismatched OpenSSL; running in an environment where the crypto provider was already set up differently elsewhere in the process.
Related errors
- failed to build reqwest client
- failed to build reqwest client
- failed to build reqwest client
- failed to build reqwest client
- failed to build reqwest client
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/f487944ee026ff3a.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/api/src/providers/openai_compat.rs:154
#[derive(Debug, Deserialize)]
struct LmStudioInstanceConfig {
#[serde(default)]
context_length: Option<u32>,
}
impl OpenAiCompatProvider {
/// Create a new compat provider. `base_url` should already include any
/// path prefix (e.g. `"https://api.groq.com/openai/v1"`).
pub fn new(
id: impl Into<String>,
name: impl Into<String>,
base_url: impl Into<String>,
) -> Self {
let http_client = reqwest::Client::builder()
.timeout(crate::request_timeout())
.build()
.expect("failed to build reqwest client");
Self {
id: ProviderId::new(id),
name: name.into(),
base_url: base_url.into(),
api_key: None,
extra_headers: Vec::new(),
quirks: ProviderQuirks::default(),
http_client,
}
}
/// Set an API key that will be sent as `Authorization: Bearer <key>`.
pub fn with_api_key(mut self, key: String) -> Self {
self.api_key = if key.is_empty() { None } else { Some(key) };
self
}
View on GitHub (pinned to b0637c97ec)