gitbutlerapp/gitbutler · warning · anyhow::Error

Request failed: {e}

Error message

Request failed: {e}

What it means

The reqwest POST to the update server (https://app.gitbutler.com/updates by default) failed at the transport layer — DNS resolution, TCP connect, TLS handshake, or the 30-second timeout fired. The error string chains the underlying reqwest error with the specific cause.

Source

Thrown at crates/but-update/src/check.rs:125

        .default_headers(headers)
        .timeout(REQUEST_TIMEOUT)
        .build()?;

    let url = url_override.unwrap_or(UPDATES_CHECK_URL).to_string();

    let result = std::thread::spawn(move || -> anyhow::Result<CheckUpdateStatus> {
        let runtime = tokio::runtime::Builder::new_current_thread()
            .enable_all()
            .build()
            .map_err(|e| anyhow::anyhow!("Failed to create runtime: {e}"))?;

        runtime.block_on(async {
            let response = client
                .post(url)
                .json(&request_body)
                .send()
                .await
                .map_err(|e| anyhow::anyhow!("Request failed: {e}"))?
                .error_for_status()
                .map_err(|e| anyhow::anyhow!("Server returned error: {e}"))?;

            let update_info = response
                .json::<CheckUpdateStatus>()
                .await
                .map_err(|e| anyhow::anyhow!("Failed to parse response: {e}"))?;

            Ok(update_info)
        })
    })
    .join()
    .map_err(|_| anyhow::anyhow!("Update check thread panicked"))?;

    // Save to cache (convert to but_db types)
    if let Ok(status) = &result {
        let now = chrono::Utc::now();

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Verify connectivity to https://app.gitbutler.com/updates (curl -I) from the same machine
  2. Configure proxy env vars (HTTPS_PROXY) if a corporate proxy is required
  3. Treat as non-fatal: update checks are optional; skip/retry later when back online
Defensive patterns

Strategy: retry

Validate before calling

// preflight connectivity before the check
if !std::net::TcpStream::connect_timeout(&"app.gitbutler.com:443".to_socket_addrs()?.next().unwrap(), std::time::Duration::from_secs(3)).is_ok() {
    return Ok(None); // offline: use cached update info instead
}

Try / catch

let mut attempt = 0;
loop {
    match check_status(app, settings, cache) {
        Err(e) if e.to_string().contains("Request failed") && attempt < 2 => { attempt += 1; std::thread::sleep(backoff(attempt)); }
        other => break other,
    }
}

Prevention

When it happens

Trigger: check_status() with no network connectivity, a proxy/firewall blocking app.gitbutler.com, DNS failure, or a response slower than the REQUEST_TIMEOUT of 30s.

Common situations: Offline or captive-portal networks; corporate proxies that MITM TLS; transient outages of the update endpoint; CI runners without egress.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/d2594cb133c3e7ce. Report an issue: GitHub.