GitoxideLabs/gitoxide · error

a non-empty checkout path has a checkout

Error message

a non-empty checkout path has a checkout

What it means

This `expect` panic (gix-tix/src/edit/rebase.rs:1081) unwraps an `Option<Id>` named `checkout` (the currently checked-out commit). The invariant: whenever `checkout_path` is non-empty, a checkout commit must have been determined earlier (the code that populated `checkout_path` always sets the commit). The panic fires if `checkout_path` is non-empty but `checkout` is `None`.

Solutions

  1. Only set `checkout_path` when a checkout commit was successfully resolved; keep the two values derived from the same source.
  2. Replace the `expect` with an explicit error: bail with a message that the repository has no resolvable checkout for the given path.
  3. Resolve the checked-out commit earlier (via `repo.head()`/worktree info) and propagate any failure instead of deferring to the assertion.

Example fix

// before
if !repeat && !checkout_path.is_empty() {
    let checkout = checkout.expect("a non-empty checkout path has a checkout");
// after
if !repeat && !checkout_path.is_empty() {
    let Some(checkout) = checkout else {
        anyhow::bail!("checkout path {:?} is set but no checked-out commit could be resolved", checkout_path);
    };
Defensive patterns

Strategy: type-guard

Validate before calling

// Before entering the checkout-dependent branch:
anyhow::ensure!(
    checkout_path.is_empty() || checkout.is_some(),
    "checkout path is set but no checked-out commit was resolved"
);

Type guard

fn resolved_checkout(checkout: Option<gix::Id>, path: &str) -> Option<gix::Id> {
    match (path.is_empty(), checkout) {
        (false, Some(id)) => Some(id),
        _ => None,
    }
}

Try / catch

// Fail with context instead of panicking:
let Some(checkout) = checkout else {
    anyhow::bail!("operation requires a checked-out commit, but none was resolved for {:?}", checkout_path);
};

Prevention

When it happens

Trigger: Running the rebase edit path where a checkout worktree path was recorded (`checkout_path` non-empty) but the corresponding `Option<Id>` remained `None` — e.g. a bare repository, a detached-worktree setup, or code path that fills `checkout_path` from config/args without resolving the checked-out commit.

Common situations: Invoking the operation in a bare repository or from a linked worktree where `checkout_exclusive`-style state is absent, or after an API/version change where the field population logic no longer matches the assertion (schema/behavior drift between gix versions for worktree state).

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/8f60b00a673ccc91. Report an issue: GitHub.

Appendix: source

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

        ..Progress::default()
    };
    report(None, progress);
    let checkout = if repo.workdir().is_some() {
        repo.head()?.id().map(gix::Id::detach)
    } else {
        None
    };
    let checkout_path: HashSet<_> = checkout
        .into_iter()
        .flat_map(|checkout| {
            affected
                .iter()
                .copied()
                .filter(move |id| graph.is_ancestor(*id, checkout))
        })
        .collect();
    if !repeat && !checkout_path.is_empty() {
        let checkout = checkout.expect("a non-empty checkout path has a checkout");
        let scan_from = if allow_pending_checkout && root == Some(checkout) {
            repo.find_commit(checkout)?
                .decode()?
                .into_owned()?
                .parents
                .first()
                .copied()
        } else {
            Some(checkout)
        };
        if let Some(id) = scan_from {
            reject_pending_checkout_path(&repo, id)?;
        }
    }
    validate(&repo, graph, &affected, removed, repeat, tree_mode)?;

    let signing = repo
        .commit_signing_options_if_enabled()

View on GitHub (pinned to e73179060b)