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 = objectView on GitHub (pinned to a221052e0d)
Solutions
- Audit proxy env vars first (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY, lowercase variants) — unset them to test whether the build succeeds
- Check SSL_CERT_FILE/SSL_CERT_DIR point at a readable PEM bundle if set
- Reproduce minimally: build a tiny reqwest client with the same tls_client_builder to isolate TLS vs proxy causes
- 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
- validate proxy URLs at config-load time, not first request
- run a startup smoke test that builds the client in the deployment environment
- fail fast at boot with env var names echoed (names only, never values)
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
- Invalid ${paramName}: '${value}'. Must be a valid integer ID
- RPC envelope contains undefined data
- RPC ${method} HTTP ${res.status}
- RPC ${method} HTTP ${res.status}
- Invalid ${paramName}: ${String(value)}. Type must be an inte
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/b15a412f58b34306.
Report an issue: GitHub.