gitbutlerapp/gitbutler · error

Failed to fetch release information for version

Error message

Failed to fetch release information for version {version}. Version may not exist. HTTP {response_code}

What it means

fetch_release got a non-200 HTTP status from the GitHub-style releases API while resolving a specific version request, and wraps the status into a descriptive error noting the version may not exist. The installer cannot proceed without release metadata.

Solutions

  1. Check the exact version string exists as a release (e.g. `but` releases page or API)
  2. Re-run after a delay if the status was 403/5xx (rate limit or transient outage)
  3. Use a valid released version or Nightly/Release mode instead
  4. Check for proxy/firewall interference with the API host

Example fix

// before
install_with_version("1.32.0")?;
// after
install_with_version("1.3.2")?; // version string verified against releases
Defensive patterns

Strategy: retry

Validate before calling

// verify the release exists before installing
let status = reqwest::Client::new()
    .head(format!("https://api.github.com/repos/OWNER/REPO/releases/tags/{version}"))
    .send().await?.status();
let exists = status == reqwest::StatusCode::OK;

Try / catch

match result {
    Err(e) if e.to_string().contains("Version may not exist") => {
        // retry with backoff for 403/5xx; validate version string for 404
    }
    other => other?,
}

Prevention

When it happens

Trigger: Requesting VersionRequest::Specific("x.y.z") where the API responds with 404 (tag does not exist), 403 (rate limit), 5xx, etc. — any non-200 status for that version's release endpoint.

Common situations: Typo in the version string, requesting a version that was unpublished/deleted, GitHub API rate limiting without auth, transient GitHub outages.

Related errors


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

Appendix: source

Thrown at crates/but-installer/src/release.rs:53

        transfer
            .write_function(|data| {
                response_data.extend_from_slice(data);
                Ok(data.len())
            })
            .context("Failed to set write function")?;
        transfer
            .perform()
            .with_context(|| format!("Failed to fetch release information from {url}"))?;
    }

    let response_code = easy
        .response_code()
        .context("Failed to get response code")?;

    if response_code != 200 {
        match &config.version_request {
            crate::config::VersionRequest::Specific(version) => {
                bail!(
                    "Failed to fetch release information for version {version}. Version may not exist. HTTP {response_code}"
                );
            }
            crate::config::VersionRequest::Nightly => {
                bail!("Failed to fetch nightly release information. HTTP {response_code}");
            }
            crate::config::VersionRequest::Release => {
                bail!("Failed to fetch release information from {url}. HTTP {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"))?;

View on GitHub (pinned to 58e5313667)