davila7/claude-code-templates · error · anyhow::Error

failed to build HTTP client: {e}

Error message

failed to build HTTP client: {e}

What it means

The Rust helper `client()` in cli-rust/src/github.rs failed to construct a reqwest blocking Client. reqwest's builder returns Err when TLS backend initialization fails or builder options (timeout, user_agent) are invalid. The anyhow! wrapper attaches 'failed to build HTTP client' with the underlying error string.

Source

Thrown at cli-rust/src/github.rs:22

use crate::constants;
use anyhow::{anyhow, Result};
use serde_json::Value;
use std::time::Duration;

/// Outcome of a raw fetch: found content, an explicit 404, or another HTTP
/// status (treated as an error by callers).
pub enum Fetched {
    Ok(String),
    NotFound,
    Status(u16),
}

fn client() -> Result<reqwest::blocking::Client> {
    reqwest::blocking::Client::builder()
        .timeout(Duration::from_secs(30))
        .user_agent(constants::user_agent())
        .build()
        .map_err(|e| anyhow!("failed to build HTTP client: {e}"))
}

/// Fetch a raw URL, distinguishing 404 from other failures so callers can show
/// the same "not found" messaging the Node CLI does.
pub fn fetch_raw(url: &str) -> Result<Fetched> {
    let resp = client()?.get(url).send()?;
    let status = resp.status();
    if status.is_success() {
        Ok(Fetched::Ok(resp.text()?))
    } else if status.as_u16() == 404 {
        Ok(Fetched::NotFound)
    } else {
        Ok(Fetched::Status(status.as_u16()))
    }
}

/// Fetch a raw URL, returning `Some(text)` only on 2xx (used for optional
/// sidecar files like `.py`/`.sh` where any failure is silently ignored).

View on GitHub (pinned to a0851ed10c)

Solutions

  1. Ensure the system has CA certificates (apt install ca-certificates / apk add ca-certificates) and retry
  2. Check reqwest Cargo features include a TLS backend (e.g. features = ["blocking", "default-tls"] or rustls-tls)
  3. Print the underlying error: run with RUST_LOG=debug or inspect {e} to see if it's TLS, DNS, or header related
  4. Verify constants::user_agent() returns a valid header value (no newlines/invalid chars)

Example fix

// Cargo.toml — before
reqwest = { version = "0.12", features = ["blocking", "json"] }
// after (explicit TLS backend)
reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] }
Defensive patterns

Strategy: fallback

Validate before calling

// Before first use, verify a client can be built once and reuse it
use once_cell::sync::Lazy;
static CLIENT: Lazy<Result<reqwest::blocking::Client>> =
    Lazy::new(|| reqwest::blocking::Client::builder()
        .timeout(Duration::from_secs(30))
        .user_agent(constants::user_agent())
        .build());

fn ensure_client() -> Result<&'static reqwest::blocking::Client> {
    CLIENT.as_ref().map_err(|e| anyhow!("failed to build HTTP client: {e}"))
}

Try / catch

// catch at the command boundary and surface a TLS/env hint
match github::fetch_raw(url) {
    Err(e) if e.to_string().contains("failed to build HTTP client") => {
        eprintln!("{e}\nHint: check that CA certificates are installed and reqwest has a TLS feature enabled");
        std::process::exit(2);
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling github::fetch_raw, fetch_raw_optional, or walk (e.g. via download_skill_tree) on a machine where the native TLS root store cannot be loaded (missing ca-certificates), or when reqwest was compiled without a TLS feature, or an invalid User-Agent header value from constants::user_agent().

Common situations: Fresh Linux container/alpine image without ca-certificates installed; building with default-features=false on reqwest; broken SSL environment variables; static binary in a minimal Docker image.

Related errors


AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28). Data as JSON: /api/errors/0cc28bcf63522084. Report an issue: GitHub.