gitbutlerapp/gitbutler · error

Signature is empty - refusing to verify without a valid sign

Error message

Signature is empty - refusing to verify without a valid signature

What it means

verify_signature() (crates/but-installer/src/install.rs:31-41) refuses to continue when the signature string is empty or whitespace-only. On macOS the value comes from platforms[<platform>].signature in the release JSON; an empty signature means the release cannot be proven authentic, and the installer will not skip minisign verification against GitButler's hardcoded public key. This is a deliberate security stop, not a parsing bug.

Source

Thrown at crates/but-installer/src/install.rs:40

        .arg("--version")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .status()
        .map(|s| s.success())
        .unwrap_or(false)
}

/// Verify the signature for a CLI installable
pub(crate) fn verify_signature(
    installable: &Path,
    signature_b64: &str,
    temp_dir: &Path,
) -> Result<()> {
    crate::ui::info("Verifying download signature...");

    // Validate signature is not empty - this is a security requirement
    if signature_b64.trim().is_empty() {
        bail!("Signature is empty - refusing to verify without a valid signature");
    }

    // GitButler's minisign public key
    let pubkey_str = "RWTrOEI+im1XYA9RBwyxnzFN/evFzJhU1lbQ70LVayWH3WRo7xQnRLD2";

    // Parse the public key
    let public_key = minisign_verify::PublicKey::from_base64(pubkey_str)
        .context("Failed to parse public key")?;

    // Decode signature from base64 and write to file
    // The signature format from the API is base64-encoded minisign signature file content
    use base64::{Engine, engine::general_purpose::STANDARD};
    let signature_bytes = STANDARD
        .decode(signature_b64)
        .context("Failed to decode signature from base64")?;

    // Write signature to temp file for minisign to parse
    let signature_file = temp_dir.join("signature.minisig");

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Retry or pick another version/channel - the defect is in the published release metadata and cannot be fixed locally
  2. Verify the release JSON at app.gitbutler.com/releases to confirm the signature field is empty for your platform
  3. Never bypass signature verification to work around this; report the broken release to GitButler (GitHub issues)
Defensive patterns

Strategy: validation

Validate before calling

// Before installing, confirm the release ships a usable signature for your platform
let release: serde_json::Value = client.get(&releases_url).send()?.json()?;
let sig = release["platforms"][&platform]["signature"].as_str().unwrap_or("");
if sig.trim().is_empty() {
    anyhow::bail!("release has no signature for {platform}; refusing to install");
}

Try / catch

if let Err(e) = but_installer::run_installation_with_version(request, false) {
    if e.to_string().contains("Signature is empty") {
        // upstream release defect: switch version/channel, never skip verification
        return but_installer::run_installation_with_version(
            but_installer::VersionRequest::Release, false);
    }
    return Err(e);
}

Prevention

When it happens

Trigger: The release JSON at app.gitbutler.com contains an empty signature for the platform entry; a caller of verify_signature passes an empty string because a field was misparsed or dropped; a release was published with the signing step failed or skipped.

Common situations: Nightly published during a signing pipeline failure; pinning a version released before signatures were added to metadata; caching layers that strip the signature field.

Related errors


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