Kuberwastaken/claurst · error · anyhow::Error

Failed to build HTTP client

Error message

Failed to build HTTP client: {}

What it means

fetch_oauth_metadata() builds a reqwest HTTP client (10s timeout) to fetch the authorization server's well-known metadata document. If reqwest cannot construct the client (TLS backend init failure, proxy misconfiguration, runtime issues), the build error is wrapped and returned. Called by begin_mcp_auth and get_valid_mcp_token.

Solutions

  1. Read the wrapped reqwest error for the concrete cause (usually TLS or proxy)
  2. Rebuild with a working TLS feature (e.g. rustls or native-tls) enabled
  3. Unset/fix malformed proxy environment variables (HTTP_PROXY/HTTPS_PROXY)
  4. Retry in a normal networked environment to rule out sandbox restrictions
Defensive patterns

Strategy: retry

Validate before calling

// sanity-check the URL is https and reachable before metadata fetch
if !server_url.starts_with("https://") {
    anyhow::bail!("OAuth requires an https server URL");
}

Try / catch

let client = reqwest::Client::builder()
    .timeout(Duration::from_secs(10))
    .build()
    .map_err(|e| {
        eprintln!("reqwest build failed (TLS/proxy?): {e}");
        e
    })?;

Prevention

When it happens

Trigger: reqwest::Client::builder().build() returns Err during fetch_oauth_metadata — typically TLS backend initialization failure or invalid global proxy/env settings.

Common situations: Static binaries missing system TLS roots; reqwest built without a TLS feature for the target platform; corporate proxy env vars (HTTPS_PROXY) malformed; embedded targets lacking the network stack.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/85cf11808ea9b149. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/mcp/src/oauth.rs:165

    verifier: &str,
) -> String {
    let challenge = pkce_challenge(verifier);
    format!(
        "{}?client_id=claurst&redirect_uri={}&response_type=code&code_challenge={}&code_challenge_method=S256",
        authorization_endpoint,
        urlencoding::encode(redirect_uri),
        challenge,
    )
}

pub async fn fetch_oauth_metadata(server_url: &str) -> anyhow::Result<McpOAuthMetadata> {
    let base_url = normalized_server_url(server_url);
    let fallback = fallback_oauth_metadata(base_url);
    let metadata_url = format!("{}/.well-known/oauth-authorization-server", base_url);
    let client = reqwest::Client::builder()
        .timeout(Duration::from_secs(10))
        .build()
        .map_err(|e| anyhow::anyhow!("Failed to build HTTP client: {}", e))?;

    match client.get(&metadata_url).send().await {
        Ok(resp) if resp.status().is_success() => {
            let meta: serde_json::Value = resp
                .json()
                .await
                .map_err(|e| anyhow::anyhow!("OAuth metadata parse error: {}", e))?;
            Ok(McpOAuthMetadata {
                authorization_endpoint: meta
                    .get("authorization_endpoint")
                    .and_then(|value| value.as_str())
                    .unwrap_or(fallback.authorization_endpoint.as_str())
                    .to_string(),
                token_endpoint: meta
                    .get("token_endpoint")
                    .and_then(|value| value.as_str())
                    .unwrap_or(fallback.token_endpoint.as_str())
                    .to_string(),

View on GitHub (pinned to b0637c97ec)