gitbutlerapp/gitbutler · error

Failed to find reference {target} in rebase editor

Error message

Failed to find reference {target} in rebase editor

What it means

`Editor::select_reference` looks up a reference by full name (e.g. `refs/heads/feature`) among the graph's steps and returns this error when the reference is not represented in the current rebase graph. Unborn branches, refs outside the workspace (e.g. `refs/remotes/...` tags or other remotes), or typos in the refname all miss. `try_select_reference` exists as the Option-returning probe.

Source

Thrown at crates/but-rebase/src/graph_rebase/mutate.rs:249

        editor.select_reference(self.as_ref())
    }
}

/// Operations for mutating the commit graph
impl<M: RefMetadata> Editor<'_, '_, M> {
    /// Get a selector to a particular commit in the graph
    pub fn select_commit(&self, target: gix::ObjectId) -> Result<Selector> {
        match self.try_select_commit(target) {
            Some(selector) => Ok(selector),
            None => Err(anyhow!("Failed to find commit {target} in rebase editor")),
        }
    }

    /// Get a selector to a particular reference in the graph
    pub fn select_reference(&self, target: &gix::refs::FullNameRef) -> Result<Selector> {
        match self.try_select_reference(target) {
            Some(selector) => Ok(selector),
            None => Err(anyhow!(
                "Failed to find reference {target} in rebase editor"
            )),
        }
    }

    /// Get a selector to a particular commit in the graph
    pub fn try_select_commit(&self, target: gix::ObjectId) -> Option<Selector> {
        for node_idx in self.graph.node_indices() {
            if let Step::Pick(Pick { id, .. }) = self.graph[node_idx]
                && id == target
            {
                return Some(self.new_selector(node_idx));
            }
        }

        None
    }

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Use the full reference name (`refs/heads/<branch>`) as `gix::refs::FullNameRef` expects
  2. Rebuild/refresh the editor graph after creating or deleting refs, then select
  3. Use `try_select_reference` when the ref may legitimately be absent, and handle None
  4. Check the ref still exists (`repo.find_reference`) to distinguish 'deleted concurrently' from 'not in graph'

Example fix

// before
let sel = editor.select_reference(name.as_ref())?; // Err: Failed to find reference ...

// after
use anyhow::Context;
let sel = editor
    .try_select_reference(name.as_ref())
    .with_context(|| format!("reference {name} not in editor graph; rebuild graph after ref changes"))?;
Defensive patterns

Strategy: validation

Validate before calling

let name = gix::refs::FullName::try_from(format!("refs/heads/{branch}"))
    .with_context(|| format!("invalid ref name for branch {branch}"))?;
let Some(sel) = editor.try_select_reference(name.as_ref()) else {
    anyhow::bail!("reference {name} not in editor graph");
};

Try / catch

match editor.select_reference(name.as_ref()) {
    Ok(sel) => sel,
    Err(e) if e.to_string().contains("Failed to find reference") => {
        anyhow::ensure!(repo.find_reference(name.as_str()).is_ok(),
            "reference {name} no longer exists (deleted concurrently)");
        rebuild_editor_and_retry(name)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `select_reference` with `refs/heads/new-branch` before it has any commits (unborn); selecting a remote-tracking or tag ref that was never added to the graph; passing a partial name like "main" instead of the full `refs/heads/main`.

Common situations: Workspace code selecting refs right after branch creation before a graph rebuild; mixing gix FullNameRef values from a different snapshot; ref deleted concurrently by another process (git CLI, another window).

Related errors


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