{"record":{"id":"0f929d430efff9da","repo":"gitbutlerapp/gitbutler","slug":"invalid-version-format-version-version-must-co-0f929d","errorCode":null,"errorMessage":"Invalid version format: {version}. Version must contain at least one alphanumeric character.","messagePattern":"Invalid version format: (.+?)\\. Version must contain at least one alphanumeric character\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-installer/src/config.rs","lineNumber":67,"sourceCode":"\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    }\n}\n\nimpl AsRef<str> for Version {\n    fn as_ref(&self) -> &str {\n        &self.0\n    }\n}","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-installer/src/config.rs#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a real version containing at least one letter or digit (`1.2.3`, `nightly`)","Debug the variable producing the value: `echo \"[$VERSION]\"` to reveal it is only punctuation","Fix the upstream extraction (e.g., grep -oE '[0-9]+\\\\.[0-9]+\\\\.[0-9]+') so digits survive into the argument"],"exampleFix":"# before\nbut-installer \"${VERSION#v}\"   # VERSION=\"v...\" -> \"...\" -> rejected\n\n# after\nVERSION=$(git describe --tags | grep -oE '[0-9]+\\\\.[0-9]+\\\\.[0-9]+' | head -1)\nbut-installer \"${VERSION:-nightly}\"","handlingStrategy":"validation","validationCode":"fn has_alphanumeric(v: &str) -> bool { v.chars().any(|c| c.is_alphanumeric()) }\nif !has_alphanumeric(&version) {\n    eprintln!(\"'{version}' has no letters or digits; expected e.g. 1.2.3 or nightly\");\n    std::process::exit(2);\n}\nlet v = Version::new(version)?;","typeGuard":"fn version_has_content(v: &str) -> bool { v.chars().any(|c| c.is_alphanumeric()) }","tryCatchPattern":"if let Err(err) = Version::new(version) {\n    if err.to_string().contains(\"at least one alphanumeric\") {\n        eprintln!(\"version string lost its digits during extraction; check the pipeline variable\");\n        std::process::exit(2);\n    }\n    return Err(err);\n}","preventionTips":["Echo the variable before use (printf '[%s]\\n' \"$VERSION\") to catch punctuation-only values","Extract versions with a digit-aware pattern (grep -oE '[0-9]+\\\\.[0-9]+\\\\.[0-9]+') rather than pure stripping"],"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"}