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

  1. Reject or re-prompt for names that contain no alphanumeric characters before calling normalize_short_name
  2. Reserve 'HEAD' client-side (case-insensitively is safest) and ask for a different name
  3. Provide a fallback slug generator that appends a stable suffix (ticket id) when sanitization empties the name
  4. 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

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


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