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

  1. 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).
  2. Add CA certificates to the container image (e.g. `apk add ca-certificates` / `apt-get install ca-certificates`).
  3. If TLS backend init is expected to fail in embedded contexts, refactor `new` to return `Result<Self, reqwest::Error>` and propagate instead of expecting.
  4. 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

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


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)