gitbutlerapp/gitbutler · error

Download of {url} failed with HTTP status: {response_code}

Error message

Download of {url} failed with HTTP status: {response_code}

What it means

download_to_string() (Linux-only path, crates/but-installer/src/download.rs:11) fetches the minisign signature file for a release with libcurl and bails when the final HTTP status is anything other than 200. The message includes the failing URL and status code. This is the signature fetch that must succeed before verify_signature() can run, so the install aborts without touching the existing installation.

Source

Thrown at crates/but-installer/src/download.rs:37

    {
        let mut transfer = easy.transfer();
        transfer
            .write_function(|data| {
                buf.borrow_mut().extend_from_slice(data);
                Ok(data.len())
            })
            .context("Failed to set write function")?;

        transfer
            .perform()
            .with_context(|| format!("Failed to download from {url}"))?;
    }

    let response_code = easy
        .response_code()
        .context("Failed to get response code")?;
    if response_code != 200 {
        bail!("Download of {url} failed with HTTP status: {response_code}");
    }

    let effective_url = easy
        .effective_url()
        .context("Failed to get effective URL")?
        .ok_or_else(|| anyhow!("Effective URL is missing"))?;

    crate::release::validate_download_url(effective_url)
        .with_context(|| format!("Download was redirected to an untrusted URL: {effective_url}"))?;

    String::from_utf8(buf.into_inner()).context("Signature file is not valid UTF-8")
}

pub(crate) fn download_file(url: &str, dest: &Path) -> Result<()> {
    let mut easy = create_client()?;

    easy.url(url)
        .with_context(|| format!("Failed to set URL: {url}"))?;

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Retry the install - transient 5xx/CDN errors are the most common cause
  2. Try a different channel/version (plain 'but-installer' for latest release) if the pinned version's signature is permanently absent
  3. curl -I the URL shown in the error message to confirm the status and whether a proxy alters it
  4. Check GitButler status/GitHub releases to confirm the artifact exists
Defensive patterns

Strategy: retry

Validate before calling

// Optional pre-flight: HEAD the signature URL before starting the install
fn artifact_reachable(url: &str) -> anyhow::Result<bool> {
    let mut easy = curl::easy::Easy::new();
    easy.url(url)?;
    easy.nobody(true)?; // HEAD request
    easy.perform()?;
    Ok(easy.response_code()? == 200)
}

Try / catch

let mut attempt = 0u32;
loop {
    match but_installer::run_installation_with_version(request.clone(), false) {
        Ok(()) => break,
        Err(e) if e.to_string().contains("failed with HTTP status") && attempt < 2 => {
            attempt += 1;
            std::thread::sleep(std::time::Duration::from_secs(2 * attempt as u64));
        }
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: The signature URL derived from the release metadata (platforms["linux-*"].url plus .minisig) returns 404, 5xx, or a proxy-injected 407/502 during download_to_string(); e.g. releases.gitbutler.com incident, signature object never uploaded for that version, or a nightly whose artifacts were pruned between metadata fetch and signature download.

Common situations: CDN incidents; corporate proxies intercepting *.gitbutler.com; pinned old versions whose signature artifacts are missing; nightly channel races during publishing.

Related errors


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