gitbutlerapp/gitbutler · error

Expected reference selector to point to a commit

Error message

Expected reference selector to point to a commit

What it means

Raised by `first_pick_parent` in crates/but-workspace/src/divergence.rs:185 while walking adjacent reference selectors to find one whose lookup step is a `Pick`. If no adjacent candidate resolves to a pick step, the function concludes the selector does not point to a commit and errors. Exposed via `tip_for_ref`.

Solutions

  1. Verify the reference resolves to a commit (`peel to commit`) before computing divergence
  2. Rebuild/refresh workspace metadata so the editor's step log matches the repository state
  3. Check the branch was created by a supported operation (not hand-edited refs)
  4. Report as a bug if a normal branch triggers it — this usually indicates an invariant violation

Example fix

// before
let tip = tip_for_ref(&editor, ref_name, &repo)?;
// after
let commit = repo.find_reference(ref_name)?.peel_to_commit()?;
let tip = tip_for_ref(&editor, ref_name, &repo)?;
Defensive patterns

Strategy: validation

Validate before calling

let commit = repo.find_reference(ref_name)?.peel_to_commit()
    .context("ref does not point to a commit; divergence cannot be computed")?;

Try / catch

match tip_for_ref(&editor, ref_name, &repo) {
    Err(e) if e.to_string().contains("Expected reference selector") => refresh_workspace_state_and_retry(),
    other => other?,
}

Prevention

When it happens

Trigger: Computing divergence for a reference whose selector history contains no `Pick` steps — e.g. the ref points at a non-commit object or the editor's step log lacks pick entries for adjacent candidates.

Common situations: Refs pointing at tags or blobs instead of commits; workspace metadata out of sync with the underlying repository; internal state corruption after interrupted operations.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/52aeb1c6809a9c9c. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-workspace/src/divergence.rs:185

            };
            Ok((candidate_commit_id, relation))
        })
        .collect()
}

fn first_pick_parent<M: RefMetadata>(
    editor: &Editor<'_, '_, M>,
    selector: Selector,
) -> Result<Selector> {
    let mut adjacent = editor.direct_parents(selector)?;
    adjacent.extend(editor.direct_children(selector)?);
    adjacent.sort_by_key(|(_, order)| *order);
    adjacent
        .into_iter()
        .find_map(|(candidate, _)| {
            matches!(editor.lookup_step(candidate).ok()?, Step::Pick(_)).then_some(candidate)
        })
        .ok_or_else(|| anyhow::anyhow!("Expected reference selector to point to a commit"))
}

fn tip_for_ref<M: RefMetadata>(
    editor: &Editor<'_, '_, M>,
    ref_name: &gix::refs::FullNameRef,
    repo: &gix::Repository,
) -> Result<Selector> {
    let reference_selector = ref_name.to_selector(editor)?;
    let head_id = repo.head_id()?.detach();
    if let Some(child_on_head_path) =
        child_on_head_first_parent_path(editor, reference_selector, head_id)?
    {
        return Ok(child_on_head_path);
    }
    first_pick_parent(editor, reference_selector).or_else(|_| {
        let tip = repo.find_reference(ref_name)?.id().detach();
        editor.select_commit(tip)
    })

View on GitHub (pinned to 58e5313667)