tinyhumansai/openhuman · error

failed to build HTTP client: {e}

Error message

failed to build HTTP client: {e}

What it means

Building the shared backend reqwest Client (platform TLS via tls_client_builder — schannel on Windows, rustls elsewhere — plus http1_only, 120s/15s timeouts, and default headers including x-sdk-name) failed. Client construction rarely fails: the realistic causes are TLS backend initialization errors or invalid proxy configuration picked up from the environment.

Source

Thrown at src/api/rest.rs:288

        }
    }
    // Which product this core is embedded in. Set at the transport level rather
    // than only on the SDK because `raw_client()` hands this same client to
    // callers that bypass the SDK entirely (multipart STT upload), and that
    // traffic needs attributing too.
    let (name, value) = crate::api::product::product_identity_header();
    default_headers.insert(name, value);

    // Platform-appropriate TLS backend: Windows → schannel (honors the OS
    // cert store, required for corporate TLS-inspection proxies); macOS /
    // Linux → rustls. See [`crate::openhuman::util::tls::tls_client_builder`].
    crate::openhuman::util::tls::tls_client_builder()
        .default_headers(default_headers)
        .http1_only()
        .timeout(Duration::from_secs(120))
        .connect_timeout(Duration::from_secs(15))
        .build()
        .map_err(|e| anyhow::anyhow!("failed to build HTTP client: {e}"))
}

/// Normalize the backend envelope while preserving OpenHuman's historical
/// response shape. In particular, `/auth/me` returns `{success,user}` rather
/// than `{success,data}`; SDK transport must not expose that envelope detail to
/// existing callers.
fn parse_api_response_value(value: Value) -> Result<Value> {
    let Some(object) = value.as_object() else {
        return Ok(value);
    };
    if let Some(user) = object.get("user").filter(|user| !user.is_null()) {
        return Ok(user.clone());
    }
    let Some(success) = object.get("success").and_then(Value::as_bool) else {
        return Ok(value);
    };
    if !success {
        let message = object

View on GitHub (pinned to a221052e0d)

Solutions

  1. Audit proxy env vars first (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY, lowercase variants) — unset them to test whether the build succeeds
  2. Check SSL_CERT_FILE/SSL_CERT_DIR point at a readable PEM bundle if set
  3. Reproduce minimally: build a tiny reqwest client with the same tls_client_builder to isolate TLS vs proxy causes
  4. Ensure the TLS feature set compiled into the binary matches the deployment platform

Example fix

# before
 export ALL_PROXY='socks'      # malformed → 'failed to build HTTP client' at startup
# after
 export ALL_PROXY='socks5://127.0.0.1:1080'
Defensive patterns

Strategy: validation

Validate before calling

fn proxy_env_sane() -> bool {
    ["HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"]
        .iter()
        .all(|k| std::env::var(k).map(|v| reqwest::Proxy::all(&v).is_ok()).unwrap_or(true))
}
assert!(proxy_env_sane(), "proxy env contains an unparseable URL");

Try / catch

let client = match build_backend_client() {
    Ok(c) => c,
    Err(e) => {
        log::error!("backend client build failed ({e}); check proxy/TLS env — names: HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, SSL_CERT_FILE");
        return Err(e);
    }
};

Prevention

When it happens

Trigger: rustls failing to load its roots (bad SSL_CERT_FILE/SSL_CERT_DIR contents on Linux); a malformed HTTP_PROXY/HTTPS_PROXY/ALL_PROXY value reqwest rejects at build time; a Windows cert store schannel cannot open; TLS features compiled in inconsistently for the target.

Common situations: Corporate proxy env vars with unsupported URI syntax set in the shell/service unit; a pinned CA bundle path that no longer exists; cross-compiled binaries missing the right TLS feature; CI images injecting odd proxy vars.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/b15a412f58b34306. Report an issue: GitHub.