janhq/jan · critical

Failed to create fallback client

Error message

Failed to create fallback client

What it means

This is a panic (.expect) from reqwest::Client::builder().build() inside the Anthropic-to-OpenAI fallback path of the proxy server. Client::build() fails when the TLS backend cannot be initialized — on Linux this usually means native-tls cannot find CA certificates (no ca-certificates package, no SSL_CERT_FILE env var). The fallback creates a fresh client to avoid connection pool contamination from the primary request.

Source

Thrown at src-tauri/src/core/server/proxy.rs:2728

                // Transform body to OpenAI format for fallback
                if let Some((url, openai_body)) = fallback_url.zip(fallback_body).and_then(|(url, body)| {
                    let json_body = serde_json::from_slice::<serde_json::Value>(&body).ok()?;
                    match transform_anthropic_to_openai(&json_body) {
                        Some(transformed) => Some((url, transformed)),
                        None => {
                            log::error!("transform_anthropic_to_openai returned None for body: {json_body}");
                            None
                        }
                    }
                }) {
                    let chat_url = format!("{}/chat/completions", url);
                    log::info!("Fallback to chat completions: {chat_url}");

                    // Create a fresh client for the fallback to avoid connection pool issues
                    let fallback_client = Client::builder()
                        .build()
                        .expect("Failed to create fallback client");

                    let mut fallback_req = fallback_client.post(&chat_url);

                    // Ensure Content-Type is set and prevent compression
                    fallback_req = fallback_req.header("Content-Type", "application/json");
                    fallback_req = fallback_req.header("Accept-Encoding", "identity");

                    for (name, value) in headers.iter() {
                        if name != hyper::header::HOST
                            && name != hyper::header::AUTHORIZATION
                            && name != "content-type"
                            && name != hyper::header::CONTENT_LENGTH
                            && name != hyper::header::ACCEPT_ENCODING
                        {
                            fallback_req = fallback_req.header(name, value);
                        }
                    }
                    if let Some(key) = fallback_api_key {

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Install CA certificates: Debian/Ubuntu `apt-get install ca-certificates`, Alpine `apk add ca-certificates`.
  2. Set SSL_CERT_FILE to the correct CA bundle path.
  3. Use rustls TLS backend instead of native-tls in the reqwest feature flags.
  4. Replace .expect with a proper error to avoid crashing the proxy.

Example fix

// before
let fallback_client = Client::builder()
    .build()
    .expect("Failed to create fallback client");

// after
let fallback_client = Client::builder()
    .build()
    .map_err(|e| format!("Failed to create fallback client: {e}"))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// At startup, verify a reqwest client can be built
fn verify_tls_available() -> bool {
    reqwest::Client::builder().build().is_ok()
}

// If false, log a clear message about missing CA certificates
if !verify_tls_available() {
    log::error!("reqwest client build failed; install ca-certificates and check SSL_CERT_FILE");
}

Try / catch

// Replace .expect with a proper error
let fallback_client = Client::builder()
    .build()
    .map_err(|e| {
        log::error!("Failed to create fallback HTTP client: {e}");
        format!("TLS/client init failed: {e}. Check CA certificates.")
    })?;

Prevention

When it happens

Trigger: Running on Linux without ca-certificates installed (minimal Docker images, Alpine without ca-certificates-bundle). The SSL_CERT_FILE or SSL_CERT_DIR env vars point to nonexistent paths. A corrupt system trust store. TLS backend initialization failure due to a FIPS or hardware crypto module issue.

Common situations: Docker Alpine images missing `apk add ca-certificates`. Distroless containers without root certificates. Proxied environments where MITM certs are not in the trust store. FIPS-mode kernels rejecting the TLS cipher negotiation.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/ac4cafcf6ffa05a1. Report an issue: GitHub.