gitbutlerapp/gitbutler · info

infinite loop should find a unique name

Error message

infinite loop should find a unique name

What it means

`find_unique_refname` (but-core/src/branch/generate.rs:31) walks `for num in start_num..` trying `base-{num}` against remote-tracking short names and existing references, returning on the first free candidate. Because `start_num..` is an infinite `usize` range whose only exits are the two `return`s, the trailing `unreachable!` is a compiler-satisfying marker, not a reachable error path; it could only execute after exhausting every `usize` value (or via arithmetic overflow, which panics on its own first).

Source

Thrown at crates/but-core/src/branch/generate.rs:84

        .category()
        .with_context(|| format!("Input branch {template} could not be categorized"))?;
    let mut candidate_short = BString::default();
    for num in start_num.. {
        candidate_short.clear();
        candidate_short.push_str(base);
        candidate_short.push(b'-');
        candidate_short.push_str(num.to_string());

        if rtb_lut.contains(candidate_short.as_bstr()) {
            continue;
        }
        let candidate_full = category.to_full_name(candidate_short.as_bstr())?;

        if repo.try_find_reference(&candidate_full)?.is_none() {
            return Ok(candidate_full);
        }
    }
    unreachable!("infinite loop should find a unique name")
}

/// Find a new unique branch name, one that doesn't exist in `repo` yet.
///
/// See caveats of [`find_unique_refname()`].
pub fn unique_canned_refname(repo: &gix::Repository) -> anyhow::Result<gix::refs::FullName> {
    let name = canned_refname(repo)?;
    find_unique_refname(repo, name.as_ref())
}

fn generate_short_name_from_signature(author: &gix::actor::Signature) -> anyhow::Result<BString> {
    let name = author.name.to_str_lossy();
    // Split by whitespace to get words
    let words: Vec<&str> = name.split_whitespace().collect();

    // Try to extract initials from words
    let prefix: Vec<&str> = words
        .iter()

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Treat any sighting as a signal of memory corruption or a forged repository state, and capture a core dump / report upstream.
  2. If you must bound it defensively, convert the loop to a `while num != usize::MAX` with an explicit error return after the bound.
  3. Do not 'fix' it by removing the return paths; they are the normal exits.
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Practically untriggerable: it would require a repository containing every suffix from `start_num` up to `usize::MAX`. Debug-build overflow of `num` panics earlier with an arithmetic message instead.

Common situations: None in practice; the string mostly shows up in code review, static analysis, or crash-aggregation greps rather than real traces.

Related errors


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