GitoxideLabs/gitoxide · error · anyhow::Error

the shortened reference name is ambiguous

Error message

the shortened reference name is ambiguous

What it means

Ambiguity check inside `resolve_ref_name`, called from `edit::todo::parse` when converting a reference name written in a `(ref)` todo line into a full `refs/...` name. The input is matched against the currently editable references by display name; if more than one editable reference shares the same shortened display name, the intent is ambiguous and parsing bails. Triggered by todos that use a short ref name that maps to multiple branches/refs; fix by writing the fully qualified ref name in the todo line.

Solutions

  1. Provide the unambiguous shortened reference name in the todo so it matches exactly one editable reference
  2. List the repository's editable references and their display names, then disambiguate the name by using its full form (e.g. refs/heads/topic instead of topic)
  3. If two editable references genuinely share a display name, rename or delete one of them so the todo can refer to a single reference
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at gix-tix/src/edit/todo.rs:1136 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/a6c3eb70dbace173. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/todo.rs:1136

            anyhow::bail!("a reference name is empty");
        }
        out.push((marked, name.into_owned()));
    }
    Ok(out)
}

fn resolve_ref_name(
    repo: &gix::Repository,
    refs: &mut Vec<rebase::ExpectedRef>,
    input: &gix::bstr::BStr,
) -> Result<gix::refs::FullName> {
    let mut matches = refs
        .iter()
        .filter(|reference| reference.editable && ref_display_name(&reference.name, refs).as_bstr() == input)
        .map(|reference| reference.name.clone());
    if let Some(name) = matches.next() {
        if matches.next().is_some() {
            anyhow::bail!("the shortened reference name is ambiguous");
        }
        return Ok(name);
    }
    let full = if input.starts_with(b"refs/") {
        input.to_owned()
    } else {
        let mut full = BString::from("refs/heads/");
        full.extend_from_slice(input);
        full
    };
    let name = gix::refs::FullName::try_from(full).context("the todo contains an invalid reference name")?;
    if name.as_bstr().starts_with(crate::history::PIN_PREFIX)
        || name.as_bstr().starts_with(crate::history::STASH_PREFIX)
        || name.as_bstr().starts_with(crate::history::REVIEW_PREFIX)
        || super::undo::is_queue_ref(name.as_bstr())
        || matches!(
            name.category(),
            Some(gix::refs::Category::Tag | gix::refs::Category::RemoteBranch)

View on GitHub (pinned to e73179060b)