BloopAI/vibe-kanban · critical

failed to build reqwest client

Error message

failed to build reqwest client

What it means

reqwest::Client::builder().build() returns a Result; it fails if TLS backend initialization, system proxy resolution, or other client setup fails. The code unwraps it with expect("failed to build reqwest client"), so a builder failure aborts the process with this panic message while constructing the LoopsMailer.

Source

Thrown at crates/remote/src/mail.rs:127

        Ok(())
    }
}

pub struct LoopsMailer {
    client: reqwest::Client,
    api_key: String,
    invite_template_id: String,
    review_ready_template_id: String,
    review_failed_template_id: String,
}

impl LoopsMailer {
    pub fn new(api_key: String) -> Self {
        let client = reqwest::Client::builder()
            .timeout(Duration::from_secs(5))
            .build()
            .expect("failed to build reqwest client");

        let invite_template_id = env_or("LOOPS_INVITE_TEMPLATE_ID", DEFAULT_INVITE_TEMPLATE_ID);
        let review_ready_template_id = env_or(
            "LOOPS_REVIEW_READY_TEMPLATE_ID",
            DEFAULT_REVIEW_READY_TEMPLATE_ID,
        );
        let review_failed_template_id = env_or(
            "LOOPS_REVIEW_FAILED_TEMPLATE_ID",
            DEFAULT_REVIEW_FAILED_TEMPLATE_ID,
        );

        Self {
            client,
            api_key,
            invite_template_id,
            review_ready_template_id,
            review_failed_template_id,
        }

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Ensure rustls crypto provider is installed (rustls::crypto::aws_lc_rs::default_provider().install_default()) before building any reqwest client
  2. Replace expect with proper error handling: return Result<Self> from LoopsMailer::new and log/propagate the reqwest::Error
  3. Check proxy-related env vars (http_proxy/https_proxy/no_proxy) for malformed URLs
  4. Verify TLS features in Cargo.toml are consistent (reqwest with rustls-tls, single crypto provider)

Example fix

// before
let client = reqwest::Client::builder().timeout(Duration::from_secs(5)).build().expect("failed to build reqwest client");
// after
let client = reqwest::Client::builder().timeout(Duration::from_secs(5)).build()
    .map_err(|e| anyhow::anyhow!("failed to build reqwest client: {e}"))?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn reqwest_buildable() -> bool {
    reqwest::Client::builder().timeout(Duration::from_secs(5)).build().is_ok()
}

Try / catch

match reqwest::Client::builder().timeout(Duration::from_secs(5)).build() {
    Ok(c) => c,
    Err(e) => { eprintln!("reqwest client build failed: {e}"); std::process::exit(1); }
}

Prevention

When it happens

Trigger: `LoopsMailer::new(api_key)` is called when reqwest cannot initialize the TLS backend (e.g. rustls crypto provider not installed or native-tls issues) or system proxy configuration is malformed.

Common situations: rustls crypto provider not installed before client construction (see install_default panics elsewhere in this codebase); conflicting reqwest/tls feature flags; invalid http_proxy/https_proxy env vars; loaded CA certificate files missing or unreadable.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/57fc648f69073455. Report an issue: GitHub.