{"record":{"id":"e1c8ef7a5b25bf4f","repo":"gitbutlerapp/gitbutler","slug":"invalid-version-format-version-version-must-co","errorCode":null,"errorMessage":"Invalid version format: {version}. Version must contain only alphanumeric characters, dots, hyphens, and plus signs.","messagePattern":"Invalid version format: (.+?)\\. Version must contain only alphanumeric characters, dots, hyphens, and plus signs\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-installer/src/config.rs","lineNumber":60,"sourceCode":"\n    /// Validate a version string format\n    fn validate(version: &str) -> Result<()> {\n        // Reject empty strings\n        if version.is_empty() {\n            bail!(\"Invalid version: empty string. Usage: but-installer [version|nightly]\");\n        }\n\n        // Reject if it looks like a flag\n        if version.starts_with('-') {\n            bail!(\"Invalid version: {version}. Usage: but-installer [version|nightly]\");\n        }\n\n        // Only allow semver-compatible characters\n        if !version\n            .chars()\n            .all(|c| c.is_alphanumeric() || c == '.' || c == '-' || c == '+')\n        {\n            bail!(\n                \"Invalid version format: {version}. Version must contain only alphanumeric characters, dots, hyphens, and plus signs.\"\n            );\n        }\n\n        // Must contain at least one alphanumeric character\n        if !version.chars().any(|c| c.is_alphanumeric()) {\n            bail!(\n                \"Invalid version format: {version}. Version must contain at least one alphanumeric character.\"\n            );\n        }\n\n        Ok(())\n    }\n\n    /// Get the version string as a &str\n    pub fn as_str(&self) -> &str {\n        &self.0\n    }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-installer/src/config.rs#L42-L78","documentation":"Thrown by but-installer's Version::validate (crates/but-installer/src/config.rs:60) when the version string contains characters outside [A-Za-z0-9.+-] — e.g., underscores, spaces, slashes, 'v' is fine but '1.2.3_beta!' or 'rel/1.2.3' are not. The check is charset-based only (it does not verify semver structure), and runs after the empty-string and leading-dash checks.","triggerScenarios":"Passing a git tag verbatim that contains '/', '_' or other symbols (e.g., `but-installer v1.2.3-beta_1` or `but-installer release/2024.1`); copy-paste artifacts like whitespace or quotes; Windows-style version strings with parentheses.","commonSituations":"Version strings sourced from branch names or tags with slashes; prerelease labels using underscores instead of hyphens; invisible characters pasted from release notes.","solutions":["Strip or replace offending characters: underscores → hyphens, remove '/' and spaces (e.g., v1.2.3-beta.1)","Use the exact tag name from the releases page, dropping any namespace prefix","In scripts, sanitize: `VERSION=$(echo \"$TAG\" | tr '/_' '--')`"],"exampleFix":"# before\nbut-installer \"release/1.2.3_beta\"   # '/' and '_' rejected\n\n# after\nbut-installer \"1.2.3-beta\"           # only alphanumerics, '.', '-', '+'","handlingStrategy":"validation","validationCode":"fn valid_version_charset(v: &str) -> bool {\n    !v.is_empty() && !v.starts_with('-')\n        && v.chars().all(|c| c.is_alphanumeric() || matches!(c, '.' | '-' | '+'))\n        && v.chars().any(|c| c.is_alphanumeric())\n}\nensure!(valid_version_charset(&version), \"version may only contain [A-Za-z0-9.+-]\");\nlet v = Version::new(version)?;","typeGuard":"fn is_installable_version(v: &str) -> bool {\n    v.chars().all(|c| c.is_alphanumeric() || matches!(c, '.' | '-' | '+'))\n        && v.chars().any(|c| c.is_alphanumeric())\n        && !v.starts_with('-')\n}","tryCatchPattern":"if let Err(err) = Version::new(version) {\n    if err.to_string().contains(\"must contain only alphanumeric\") {\n        eprintln!(\"clean the version string: allowed chars are letters, digits, '.', '-', '+'\");\n        std::process::exit(2);\n    }\n    return Err(err);\n}","preventionTips":["Convert '_' to '-' in prerelease labels; drop '/' namespaces from tag-based versions","Sanitize in scripts: VERSION=$(printf '%s' \"$TAG\" | tr '/_' '--') before invoking the installer"],"tags":["but-installer","version","cli","validation","rust"],"backgroundTag":"invalid-version-string","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}