{"record":{"id":"8f60b00a673ccc91","repo":"GitoxideLabs/gitoxide","slug":"a-non-empty-checkout-path-has-a-checkout","errorCode":null,"errorMessage":"a non-empty checkout path has a checkout","messagePattern":"a non-empty checkout path has a checkout","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/rebase.rs","lineNumber":1081,"sourceCode":"        ..Progress::default()\n    };\n    report(None, progress);\n    let checkout = if repo.workdir().is_some() {\n        repo.head()?.id().map(gix::Id::detach)\n    } else {\n        None\n    };\n    let checkout_path: HashSet<_> = checkout\n        .into_iter()\n        .flat_map(|checkout| {\n            affected\n                .iter()\n                .copied()\n                .filter(move |id| graph.is_ancestor(*id, checkout))\n        })\n        .collect();\n    if !repeat && !checkout_path.is_empty() {\n        let checkout = checkout.expect(\"a non-empty checkout path has a checkout\");\n        let scan_from = if allow_pending_checkout && root == Some(checkout) {\n            repo.find_commit(checkout)?\n                .decode()?\n                .into_owned()?\n                .parents\n                .first()\n                .copied()\n        } else {\n            Some(checkout)\n        };\n        if let Some(id) = scan_from {\n            reject_pending_checkout_path(&repo, id)?;\n        }\n    }\n    validate(&repo, graph, &affected, removed, repeat, tree_mode)?;\n\n    let signing = repo\n        .commit_signing_options_if_enabled()","sourceCodeStart":1063,"sourceCodeEnd":1099,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/rebase.rs#L1063-L1099","documentation":"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`.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Only set `checkout_path` when a checkout commit was successfully resolved; keep the two values derived from the same source.","Replace the `expect` with an explicit error: bail with a message that the repository has no resolvable checkout for the given path.","Resolve the checked-out commit earlier (via `repo.head()`/worktree info) and propagate any failure instead of deferring to the assertion."],"exampleFix":"// before\nif !repeat && !checkout_path.is_empty() {\n    let checkout = checkout.expect(\"a non-empty checkout path has a checkout\");\n// after\nif !repeat && !checkout_path.is_empty() {\n    let Some(checkout) = checkout else {\n        anyhow::bail!(\"checkout path {:?} is set but no checked-out commit could be resolved\", checkout_path);\n    };","handlingStrategy":"type-guard","validationCode":"// Before entering the checkout-dependent branch:\nanyhow::ensure!(\n    checkout_path.is_empty() || checkout.is_some(),\n    \"checkout path is set but no checked-out commit was resolved\"\n);","typeGuard":"fn resolved_checkout(checkout: Option<gix::Id>, path: &str) -> Option<gix::Id> {\n    match (path.is_empty(), checkout) {\n        (false, Some(id)) => Some(id),\n        _ => None,\n    }\n}","tryCatchPattern":"// Fail with context instead of panicking:\nlet Some(checkout) = checkout else {\n    anyhow::bail!(\"operation requires a checked-out commit, but none was resolved for {:?}\", checkout_path);\n};","preventionTips":["Derive `checkout_path` and the checkout `Id` from the same resolution step so they cannot diverge.","Reject the operation early in bare or detached-worktree repositories where no checkout exists.","Replace expect() with explicit error propagation when the invariant depends on repo state."],"tags":["panic","worktree","checkout","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}