gitbutlerapp/gitbutler · error · anyhow::Error
Could not turn {name:?} into a valid reference name
Error message
Could not turn {name:?} into a valid reference name What it means
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.
Source
Thrown at crates/but-core/src/branch/normalize.rs:41
break;
}
}
let mut previous_is_hyphen = false;
sanitized.retain(|b| {
if *b == b'-' {
if previous_is_hyphen {
return false;
}
previous_is_hyphen = true;
} else {
previous_is_hyphen = false;
}
true
});
if sanitized.is_empty() || sanitized == "HEAD" {
bail!("Could not turn {name:?} into a valid reference name")
}
Ok(sanitized)
}
View on GitHub (pinned to caf1f223d3)
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
Example fix
// before
let name = but_core::branch::normalize_short_name(input)?; // panics flow on "---"
// after: pre-validate in the caller
fn usable_branch_name(input: &bstr::BStr) -> bool {
let has_alnum = input.iter().any(|b| b.is_ascii_alphanumeric());
has_alnum && !input.eq_ignore_ascii_case(b"HEAD")
}
anyhow::ensure!(usable_branch_name(input), "pick a name with letters or digits");
let name = but_core::branch::normalize_short_name(input)?; Defensive patterns
Strategy: validation
Validate before calling
// reject names that cannot survive sanitization, before calling the API
fn usable_branch_name(input: &bstr::BStr) -> bool {
input.iter().any(|b| b.is_ascii_alphanumeric())
&& !input.eq_ignore_ascii_case(b"HEAD")
} Type guard
fn is_normalizable_branch_name(input: &bstr::BStr) -> bool {
input.iter().any(|b| b.is_ascii_alphanumeric()) && !input.eq_ignore_ascii_case(b"HEAD")
} Try / catch
match but_core::branch::normalize_short_name(input) {
Err(e) if e.to_string().contains("valid reference name") =>
Err(anyhow!("pick a branch name containing letters or digits")),
r => r?,
} Prevention
- 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
When it happens
Trigger: 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").
Common situations: 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 '-'.
Related errors
- Invalid branch name: {err}
- Invalid message format
- HTTP Error ${response.statusText}: ${text}
- Invalid section for global key: {key}
- Branch '{ref_name}' has no tracking branch
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/e505aed21ef4b205.
Report an issue: GitHub.