GitoxideLabs/gitoxide · error

checked above

Error message

checked above

What it means

Panic from `.expect("checked above")` when processing deferred ref deletions during branch updates in gix-tix rebase. The enclosing code just matched `expected.old.is_some()` in the `defer` condition, so the expect asserts the retained value is still `Some`. It can only fire if `expected.old` was somehow mutated or the retain predicate logic changed — i.e. an internal invariant, not a user-triggerable error.

Solutions

  1. Verify the library version; upgrade gix-tix if this panic is reachable, as it indicates a broken invariant.
  2. Wrap the operation in `catch_unwind` only as a last resort; prefer reproducing and reporting the bug.
  3. Ensure ref-update expectations come from the library's own computation, not hand-built values with missing `old` targets.
Defensive patterns

Strategy: try-catch

Validate before calling

if expected.name == current_ref && expected.old.is_none() {
    return Err(anyhow::anyhow!("cannot defer deletion of ref without known old value"));
}

Type guard

fn is_deferable(e: &ExpectedRef) -> bool {
    e.name == current_ref && e.old.is_some() && e.new.is_none()
}

Try / catch

let out = std::panic::catch_unwind(AssertUnwindSafe(|| update_refs(...)));
if out.is_err() { anyhow::bail!("ref update panicked; report a gix-tix bug"); }

Prevention

When it happens

Trigger: Calling an update/finish operation that deletes the currently checked-out branch; the panic only occurs on a code defect where the `defer` condition and the `expect` disagree about `expected.old`.

Common situations: Attempting to delete the checked-out branch as part of a rebase update while selecting another checkout; normally this path works and errors earlier with 'cannot delete the checked-out branch...'.

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 GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/21beb11f9dc536d0. Report an issue: GitHub.

Appendix: source

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

                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,
        )?;
        for (transitioned, transition) in transitions.iter().enumerate() {
            if let Err(err) = super::forget::apply_tree_transition(&transition.workdir, transition.old, transition.new)
            {
                return rollback(

View on GitHub (pinned to e73179060b)