{"record":{"id":"e505aed21ef4b205","repo":"gitbutlerapp/gitbutler","slug":"could-not-turn-name-into-a-valid-reference-nam","errorCode":null,"errorMessage":"Could not turn {name:?} into a valid reference name","messagePattern":"Could not turn (.+?) into a valid reference name","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-core/src/branch/normalize.rs","lineNumber":41,"sourceCode":"            break;\n        }\n    }\n\n    let mut previous_is_hyphen = false;\n    sanitized.retain(|b| {\n        if *b == b'-' {\n            if previous_is_hyphen {\n                return false;\n            }\n            previous_is_hyphen = true;\n        } else {\n            previous_is_hyphen = false;\n        }\n        true\n    });\n\n    if sanitized.is_empty() || sanitized == \"HEAD\" {\n        bail!(\"Could not turn {name:?} into a valid reference name\")\n    }\n\n    Ok(sanitized)\n}\n","sourceCodeStart":23,"sourceCodeEnd":46,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-core/src/branch/normalize.rs#L23-L46","documentation":"normalize_short_name() sanitizes free-typed input with gix's reference-name sanitizer, trims leading/trailing '.', '-', '/' and collapses repeated hyphens; if nothing survives — or the result is exactly the reserved name 'HEAD' — it bails because the input cannot become a valid short ref name.","triggerScenarios":"Passing a branch name consisting solely of separators/invalid characters ('...', '---', '/', '-.-') that sanitize+trim reduces to empty, or passing the literal reserved name 'HEAD' (in any casing that sanitizes to exactly b\"HEAD\").","commonSituations":"User-typed branch names from a dialog with no validation; names auto-generated from tickets whose title collapsed to punctuation after stripping invalid chars; automation deriving branch names from filenames like '-'.","solutions":["Reject or re-prompt for names that contain no alphanumeric characters before calling normalize_short_name","Reserve 'HEAD' client-side (case-insensitively is safest) and ask for a different name","Provide a fallback slug generator that appends a stable suffix (ticket id) when sanitization empties the name","Trim/normalize user input first so obvious separator-only names never reach the API"],"exampleFix":"// before\nlet name = but_core::branch::normalize_short_name(input)?; // panics flow on \"---\"\n\n// after: pre-validate in the caller\nfn usable_branch_name(input: &bstr::BStr) -> bool {\n    let has_alnum = input.iter().any(|b| b.is_ascii_alphanumeric());\n    has_alnum && !input.eq_ignore_ascii_case(b\"HEAD\")\n}\nanyhow::ensure!(usable_branch_name(input), \"pick a name with letters or digits\");\nlet name = but_core::branch::normalize_short_name(input)?;","handlingStrategy":"validation","validationCode":"// reject names that cannot survive sanitization, before calling the API\nfn usable_branch_name(input: &bstr::BStr) -> bool {\n    input.iter().any(|b| b.is_ascii_alphanumeric())\n        && !input.eq_ignore_ascii_case(b\"HEAD\")\n}","typeGuard":"fn is_normalizable_branch_name(input: &bstr::BStr) -> bool {\n    input.iter().any(|b| b.is_ascii_alphanumeric()) && !input.eq_ignore_ascii_case(b\"HEAD\")\n}","tryCatchPattern":"match but_core::branch::normalize_short_name(input) {\n    Err(e) if e.to_string().contains(\"valid reference name\") =>\n        Err(anyhow!(\"pick a branch name containing letters or digits\")),\n    r => r?,\n}","preventionTips":["Validate user-typed branch names client-side (at least one alphanumeric; reject HEAD)","When deriving names from titles/tickets, keep a guaranteed alphanumeric token like the ticket id","Test name generators with separator-only and unicode-only inputs"],"tags":["git","ref-name","validation","branch"],"backgroundTag":"invalid-branch-name","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}