gitbutlerapp/gitbutler · error

Download failed, the download artifact could not be found…

Error message

Download failed, the download artifact could not be found. Most likely, the but CLI has not been published for the requested version.

What it means

`download_file` treats HTTP 403 from the release/download server as a special case: the artifact simply is not there for the requested version. It bails with this explicit message rather than a generic HTTP error, because GitButler's artifact host returns 403 (not 404) for missing files.

Solutions

  1. Verify the requested version is actually published (check the release on the GitButler releases page / latest.json).
  2. Retry later — artifacts may still be uploading for a fresh release.
  3. Omit the version pin and install/upgrade to the latest published version.
  4. Check whether your platform's artifact exists for that specific release; if not, build from source.

Example fix

// before
let cfg = Config::new_with_version(os, arch, VersionReq::parse("0.9.0")?, ...)?;
download_and_install_app(&cfg)?;
// after
let cfg = Config::new_with_version(os, arch, "latest".parse()?, ...)?; // or retry later
download_and_install_app(&cfg)?;
Defensive patterns

Strategy: fallback

Validate before calling

let status = reqwest::blocking::Client::new()
    .head(&artifact_url).send()?.status();
if status.as_u16() == 403 {
    anyhow::bail!("artifact for version {} not published yet", version);
}

Try / catch

match download_and_install_app(&config) {
    Err(e) if e.to_string().contains("has not been published") => {
        eprintln!("version not available; falling back to latest");
        download_and_install_app(&Config::new_with_version(os, arch, "latest".parse()?, ...)?)?;
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling download_and_install_app for a version whose platform artifact was never uploaded — e.g. `but upgrade` to a brand-new release before CI finished publishing, an unpublished/typo'd version string, or a platform (like linux-aarch64) excluded from that release.

Common situations: Upgrading immediately after a release announcement before artifacts propagate; pinning a specific old/new version that lacks your platform's build; corporate proxies rewriting 404s into 403s.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/3060d58255a79885. Report an issue: GitHub.

Appendix: source

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

        // Check if we had a write error
        if let Some(io_err) = write_error.borrow_mut().take() {
            // Clear progress line before showing error
            crate::ui::println_empty();
            return Err(io_err).context("Failed to write downloaded data");
        }

        // If perform failed for other reasons, propagate that error
        perform_result.with_context(|| format!("Failed to download from {url}"))?;
    }

    // Clear progress line
    crate::ui::println_empty();

    let response_code = easy
        .response_code()
        .context("Failed to get response code")?;
    if response_code == 403 {
        bail!(
            "Download failed, the download artifact could not be found. Most likely, the but CLI has not been published for the requested version."
        )
    } else if response_code != 200 {
        bail!("Download failed with HTTP status: {response_code}");
    }

    // Validate the effective URL after following redirects
    // This protects against malicious redirects to untrusted domains or insecure protocols
    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}"))?;

    Ok(())
}

View on GitHub (pinned to 58e5313667)