gitbutlerapp/gitbutler · error

Invalid version format: {version}. Version must contain at l

Error message

Invalid version format: {version}. Version must contain at least one alphanumeric character.

What it means

Thrown by but-installer's Version::validate (crates/but-installer/src/config.rs:67) when the version string passes the charset check but contains no alphanumeric character at all — strings like "...", "-", or "+.+". It is the final validation rule, catching inputs that are technically composed of allowed punctuation but carry no version information.

Source

Thrown at crates/but-installer/src/config.rs:67

        // Reject if it looks like a flag
        if version.starts_with('-') {
            bail!("Invalid version: {version}. Usage: but-installer [version|nightly]");
        }

        // Only allow semver-compatible characters
        if !version
            .chars()
            .all(|c| c.is_alphanumeric() || c == '.' || c == '-' || c == '+')
        {
            bail!(
                "Invalid version format: {version}. Version must contain only alphanumeric characters, dots, hyphens, and plus signs."
            );
        }

        // Must contain at least one alphanumeric character
        if !version.chars().any(|c| c.is_alphanumeric()) {
            bail!(
                "Invalid version format: {version}. Version must contain at least one alphanumeric character."
            );
        }

        Ok(())
    }

    /// Get the version string as a &str
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl AsRef<str> for Version {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Pass a real version containing at least one letter or digit (`1.2.3`, `nightly`)
  2. Debug the variable producing the value: `echo "[$VERSION]"` to reveal it is only punctuation
  3. Fix the upstream extraction (e.g., grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+') so digits survive into the argument

Example fix

# before
but-installer "${VERSION#v}"   # VERSION="v..." -> "..." -> rejected

# after
VERSION=$(git describe --tags | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+' | head -1)
but-installer "${VERSION:-nightly}"
Defensive patterns

Strategy: validation

Validate before calling

fn has_alphanumeric(v: &str) -> bool { v.chars().any(|c| c.is_alphanumeric()) }
if !has_alphanumeric(&version) {
    eprintln!("'{version}' has no letters or digits; expected e.g. 1.2.3 or nightly");
    std::process::exit(2);
}
let v = Version::new(version)?;

Type guard

fn version_has_content(v: &str) -> bool { v.chars().any(|c| c.is_alphanumeric()) }

Try / catch

if let Err(err) = Version::new(version) {
    if err.to_string().contains("at least one alphanumeric") {
        eprintln!("version string lost its digits during extraction; check the pipeline variable");
        std::process::exit(2);
    }
    return Err(err);
}

Prevention

When it happens

Trigger: Passing a placeholder or mangled value such as `but-installer ...` or a variable that decayed to punctuation; a script computing a version suffix that ends up as just dots/hyphens; empty-after-cleaning transformations in CI pipelines.

Common situations: Automation producing 'v' + stripped digits where the digits were empty; users passing literal ellipsis from examples; sed/awk cleanup steps that remove all digits from the version string.

Related errors


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