googleworkspace/cli · critical · GwsError
5
5
Error message
Failed to build HTTP client: {e} What it means
`build_client_inner()` failed: `reqwest::Client::builder()...build()` returned an error before any request was made. With this builder configuration (default headers + a 10s-class connect timeout) the realistic failure modes are TLS-backend initialization (native-tls/OpenSSL load failure or rustls provider init problem) and system DNS-resolver initialization failure. Everything in gws that talks HTTP goes through this client, so the first network-touching command of a session fails here.
Source
Thrown at crates/google-workspace/src/client.rs:46
let mut headers = HeaderMap::new();
let name = env!("CARGO_PKG_NAME");
let version = env!("CARGO_PKG_VERSION");
// Format: gl-rust/name-version (the gl-rust/ prefix is fixed)
let client_header = format!("gl-rust/{}-{}", name, version);
if let Ok(header_value) = HeaderValue::from_str(&client_header) {
headers.insert("x-goog-api-client", header_value);
}
reqwest::Client::builder()
.default_headers(headers)
.connect_timeout(std::time::Duration::from_secs(CONNECT_TIMEOUT_SECS))
.build()
.map_err(|e| format!("Failed to build HTTP client: {e}"))
}
pub fn build_client() -> Result<reqwest::Client, crate::error::GwsError> {
build_client_inner().map_err(|message| crate::error::GwsError::Other(anyhow::anyhow!(message)))
}
/// Returns a shared reqwest client clone backed by a single global connection pool.
///
/// `reqwest::Client` is cheap to clone, so callers can take ownership of the
/// returned value while still sharing pooled connections underneath.
pub fn shared_client() -> Result<reqwest::Client, crate::error::GwsError> {
static CLIENT: OnceLock<Result<reqwest::Client, String>> = OnceLock::new();
match CLIENT.get_or_init(build_client_inner) {
Ok(client) => Ok(client.clone()),
Err(message) => Err(crate::error::GwsError::Other(anyhow::anyhow!(
message.clone()
))),
}
}
/// Send an HTTP request with automatic retry on 429 (rate limit) responsesView on GitHub (pinned to a3768d0e82)
Solutions
- Run `ldd $(which gws)` and install the matching OpenSSL runtime (e.g. `apt install libssl3`) if a symbol is unresolved.
- In minimal containers, add ca-certificates and ensure /etc/resolv.conf exists.
- Prefer the statically-linked release artifacts (or rustls-TLS builds) for portable deployment.
- Verify with a trivial call (`gws auth status`) after fixing — the error surfaces on first client construction.
Example fix
# before — binary copied onto a host with old OpenSSL ./gws drive files list # -> Failed to build HTTP client: failed to init TLS backend # after — install matching runtime libs / CA bundle, or ship the static binary apt-get install -y libssl3 ca-certificates ./gws drive files list
Defensive patterns
Strategy: try-catch
Validate before calling
// Fail fast at startup instead of mid-command
fn http_stack_ok() -> bool {
google_workspace::client::build_client().is_ok()
} Try / catch
let client = match google_workspace::client::build_client() {
Ok(c) => c,
Err(GwsError::Other(e)) if e.to_string().contains("Failed to build HTTP client") => {
eprintln!("TLS/resolver init failed — check OpenSSL libs, ca-certificates, and /etc/resolv.conf");
std::process::exit(3);
}
Err(e) => return Err(e),
}; Prevention
- Deploy the official statically-linked gws releases for cross-distro portability.
- In Docker, base images on ones shipping ca-certificates (alpine: `apk add ca-certificates`).
- Smoke-test `gws auth status` in new environments before scheduling real workloads.
When it happens
Trigger: Running the gws binary on a host whose OpenSSL shared libraries are missing or the wrong major version (native-tls builds); a musl/alpine image lacking ca-certificates; a system where getaddrinfo/resolver init fails (no /etc/resolv.conf in a minimal container); an OS/cert-store incompatibility after a distro upgrade.
Common situations: Copying the binary between distros with different OpenSSL (libssl3 vs 1.1); scratch/distroless containers missing CA bundles and resolver config; Nix/GNU Guix dynamic-linking mismatches; stripped-down VMs.
Related errors
- Pub/Sub pull failed: {e}
- Failed to fetch message: {e}
- Failed to fetch sendAs settings: {e}
- People API request failed: {e}
- Failed to fetch attachment: {e}
AI-assisted analysis of googleworkspace/cli@a3768d0e82 (2026-08-16).
Data as JSON: /api/errors/02f0786183fa55fd.
Report an issue: GitHub.