GitoxideLabs/gitoxide · error

cannot delete the checked-out branch without selecting…

Error message

cannot delete the checked-out branch without selecting another checkout

What it means

A ref-update batch tried to delete the currently checked-out branch while the session had neither selected another checkout nor requested a checkout after finish (or the repo is bare). Deleting HEAD's branch would leave HEAD dangling, so the update is rejected before applying deletions.

Solutions

  1. Select another branch/commit for checkout (`selected`) before deleting the current branch
  2. Set `checkout_after_finish = true` so the tool moves HEAD off the branch first
  3. Skip the branch currently pointed at by HEAD in the deletion list

Example fix

// before
session.delete_ref(current_branch)?;
// after
if current_branch == repo.head_branch() {
    session.select_checkout(other_branch);
}
session.delete_ref(current_branch)?;
Defensive patterns

Strategy: validation

Validate before calling

fn deletion_is_safe(head_branch: &RefName, targets: &[RefName], selected: Option<&RefName>, checkout_after_finish: bool, bare: bool) -> bool {
    !targets.contains(&head_branch) || selected.is_some() || checkout_after_finish || bare == false && false
}

Try / catch

match result {
    Err(e) if e.to_string().contains("checked-out branch") => {
        eprintln!("select another checkout or enable checkout-after-finish before deleting HEAD's branch");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling the rebase/ref-edit session with a deletion of the branch that `HEAD` points to, with `self.selected == None` and `checkout_after_finish == false` in a worktree repo, or any such deletion in a bare repo where checkout re-selection is impossible.

Common situations: Automation pruning 'stale' branches that unknowingly includes the checked-out one; scripts deleting the feature branch right after rebasing while still on it; deleting branches parsed from an unfiltered ref list.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at gix-tix/src/edit/rebase.rs:2214

        for transition in &transitions {
            super::forget::preflight_tree_transition(
                &transition.repo,
                &transition.workdir,
                transition.old,
                transition.new,
            )?;
        }
        let head = self.repo.head()?;
        let unborn = head.is_unborn();
        let current_ref = head.referent_name().map(ToOwned::to_owned);
        let mut deferred_ref_deletions = Vec::new();
        if let (Some(expected_refs), Some(current_ref)) = (&mut self.expected_refs, current_ref) {
            if expected_refs
                .iter()
                .any(|expected| expected.name == current_ref && expected.old.is_some() && expected.new.is_none())
                && (self.repo.workdir().is_none() || (self.selected.is_none() && !self.checkout_after_finish))
            {
                anyhow::bail!("cannot delete the checked-out branch without selecting another checkout");
            }
            expected_refs.retain(|expected| {
                let defer = expected.name == current_ref && expected.old.is_some() && expected.new.is_none();
                if defer {
                    deferred_ref_deletions.push((expected.name.clone(), expected.old.expect("checked above")));
                }
                !defer
            });
        }
        let updated_refs = update_refs(
            &self.repo,
            &self.rewritten,
            unborn,
            self.selected,
            &self.committer,
            self.expected_refs.take(),
            (&self.pins, &self.delete_refs),
            resource_edits,

View on GitHub (pinned to e73179060b)