gitbutlerapp/gitbutler · error

Expected selector to point to a reference

Error message

Expected selector to point to a reference

What it means

LookupStep::lookup_reference resolves a Selector and asserts the step is a Step::Reference, returning the ref's FullName. If the selector resolves to any other step (e.g. a commit Pick), the request is invalid and the library bails.

Solutions

  1. Inspect editor.lookup_step(selector) to confirm it is Step::Reference first
  2. Use lookup_pick when the selector targets a commit
  3. Obtain a fresh selector for the reference from the current editor

Example fix

// before
let refname = editor.lookup_reference(selector)?; // selector is a commit
// after
let refname = match editor.lookup_step(selector)? {
    Step::Reference { refname, .. } => refname,
    Step::Pick(_) => bail!("expected a reference selector"),
    _ => bail!("unsupported step"),
};
Defensive patterns

Strategy: type-guard

Validate before calling

match editor.lookup_step(selector)? { Step::Reference { .. } => {}, _ => bail!("not a reference") }

Type guard

fn is_reference_step(editor: &Editor<impl RefMetadata>, s: Selector) -> bool {
    matches!(editor.lookup_step(s), Ok(Step::Reference { .. }))
}

Try / catch

match editor.lookup_reference(selector) {
    Ok(refname) => refname,
    Err(_) => bail!("selector does not point at a reference"),
}

Prevention

When it happens

Trigger: Calling lookup_reference with a selector that resolves to a Pick (commit) or other non-Reference step — e.g. asking for the branch name of a commit selector, or a stale selector after graph mutation.

Common situations: Renaming/moving branches while accidentally passing commit selectors; selectors invalidated by prior move/drop operations shifting node identities.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at crates/but-rebase/src/graph_rebase/mod.rs:560

/// Provides lookup for different steps that a selector might point to.
pub trait LookupStep {
    /// Look up the step that a given selector corresponds to.
    fn lookup_step(&self, selector: Selector) -> Result<Step>;

    /// Look up the step a given selector and assert it's a pick.
    fn lookup_pick(&self, selector: Selector) -> Result<gix::ObjectId> {
        match self.lookup_step(selector)? {
            Step::Pick(Pick { id, .. }) => Ok(id),
            _ => bail!("Expected selector to point to a pick"),
        }
    }

    /// Look up the step a given selector and assert it's a pick.
    fn lookup_reference(&self, selector: Selector) -> Result<gix::refs::FullName> {
        match self.lookup_step(selector)? {
            Step::Reference { refname, .. } => Ok(refname),
            _ => bail!("Expected selector to point to a reference"),
        }
    }
}

impl<M: RefMetadata> LookupStep for Editor<'_, '_, M> {
    fn lookup_step(&self, selector: Selector) -> Result<Step> {
        lookup_step(&self.graph, &self.history, selector)
    }
}

impl<M: RefMetadata> LookupStep for SuccessfulRebase<'_, '_, M> {
    fn lookup_step(&self, selector: Selector) -> Result<Step> {
        lookup_step(&self.graph, &self.history, selector)
    }
}

impl<M: RefMetadata> LookupStep for MaterializeOutcome<'_, '_, M> {
    fn lookup_step(&self, selector: Selector) -> Result<Step> {

View on GitHub (pinned to 58e5313667)