gitbutlerapp/gitbutler · error

API returned version

Error message

API returned version {} but requested version {}

What it means

After parsing the release JSON, fetch_release verifies that for a Specific version request the API-returned release.version equals the requested string. A mismatch indicates the resolved release differs from what was asked, so the installer refuses to avoid installing the wrong version.

Solutions

  1. Compare the requested string against the actual release tag format (leading 'v', suffixes)
  2. Request the exact tag as published by the API
  3. Clear any intermediary cache/proxy serving stale release metadata
  4. Update the installer — server-side endpoint behavior may have changed

Example fix

// before
install_with_version("v1.2.3")?;
// after
install_with_version("1.2.3")?; // match the tag exactly as published
Defensive patterns

Strategy: validation

Validate before calling

// normalize and compare version strings before requesting
let requested = version.trim_start_matches('v');
assert_eq!(requested, expected_tag, "version must match published tag exactly");

Try / catch

match result {
    Err(e) if e.to_string().contains("API returned version") => {
        // compare requested vs returned; fix version string format and retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: The API redirected or resolved the request to a different release than requested (e.g. version moved, alias endpoint, or server returning latest instead of the specific tag); or the version string format differs (e.g. "1.2.3" vs "v1.2.3").

Common situations: Requesting "v1.2.3" when releases are tagged "1.2.3" (or vice versa), server-side aliasing to latest, cache serving a different release metadata,上游 API behavior changes.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

    // 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"))?;

    validate_api_url(effective_url).with_context(|| {
        format!("Release API was redirected to an untrusted URL: {effective_url}")
    })?;

    let release: Release =
        serde_json::from_slice(&response_data).context("Failed to parse release information")?;

    // Verify we got the version we requested (skip check for nightly)
    if let crate::config::VersionRequest::Specific(ref requested) = config.version_request
        && release.version != requested.as_str()
    {
        bail!(
            "API returned version {} but requested version {}",
            release.version,
            requested
        );
    }

    Ok(release)
}

/// Common URL validation logic for GitButler domains.
///
/// Validates HTTPS protocol, parses URL, and checks the host against a predicate.
fn validate_gitbutler_url(
    url: &str,
    url_type: &str,
    is_host_valid: impl Fn(&str) -> bool,
) -> Result<()> {
    // Only allow HTTPS URLs

View on GitHub (pinned to 58e5313667)