{"record":{"id":"8ea09b34a088c932","repo":"GitoxideLabs/gitoxide","slug":"the-root-of-a-repeated-rebase-must-be-pending","errorCode":null,"errorMessage":"the root of a repeated rebase must be pending","messagePattern":"the root of a repeated rebase must be pending","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/rebase.rs","lineNumber":2552,"sourceCode":"}\n\nfn validate(\n    repo: &gix::Repository,\n    graph: &HistoryGraph,\n    affected: &[ObjectId],\n    removed: bool,\n    repeat: bool,\n    tree: Tree,\n) -> Result<()> {\n    for (position, id) in affected.iter().enumerate() {\n        let parents = graph.parents_of(*id).context(\"an affected commit is incomplete\")?;\n        if parents.len() > 1 && (position > 0 || removed || tree == Tree::CherryPick) {\n            anyhow::bail!(\"descendant merge commits cannot be rebased\");\n        }\n        if repeat && position == 0 {\n            let commit = repo.find_commit(*id)?.decode()?.into_owned()?;\n            if !is_pending(&commit) {\n                anyhow::bail!(\"the root of a repeated rebase must be pending\");\n            }\n        }\n    }\n    if repeat\n        && let Some(base) = affected.first()\n        && let Some(parent) = graph.parents_of(*base).and_then(|parents| parents.first().copied())\n        && is_pending(&repo.find_commit(parent)?.decode()?.into_owned()?)\n    {\n        anyhow::bail!(\"the parent of a repeated rebase must not be pending\");\n    }\n    Ok(())\n}\n\nfn reject_pending_checkout_path(repo: &gix::Repository, mut id: ObjectId) -> Result<()> {\n    let mut seen = HashSet::new();\n    while seen.insert(id) {\n        let commit = repo.find_commit(id)?.decode()?.into_owned()?;\n        if is_pending(&commit) {","sourceCodeStart":2534,"sourceCodeEnd":2570,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/rebase.rs#L2534-L2570","documentation":"This error is thrown during rebase edit validation in gix-tix. When an operation repeats a rebase (the `repeat` flag with the edited commit at position 0, i.e. it is the root of the rebased range), the root commit must itself be in a 'pending' rebase state. If the root commit is not pending, the repeated rebase would start from a commit that is not part of an unfinished rebase, so the edit is rejected.","triggerScenarios":"Calling a rebase-edit operation with `repeat` enabled where the first commit in the edit range (position == 0, single-parent commit whose id is `*id`) decodes to a commit that `is_pending()` reports as NOT pending. This happens in the validation loop after the merge-commit check (parents.len() > 1 && (position > 0 || removed || tree == Tree::CherryPick)).","commonSituations":"Re-running a stored/repeated rebase script after the pending rebase was already completed, aborted, or its root was rewritten by an earlier edit; pointing the edit at the wrong (already-finalized) root commit.","solutions":["Ensure the root commit of the repeated rebase is still in pending state before invoking the edit, or omit `repeat`/start the range at position > 0.","Re-create or refresh the pending rebase state so the root is pending again.","Pick the correct root commit id for the in-progress rebase instead of a completed one.","If the rebase is actually finished, perform a normal (non-repeated) rebase edit instead."],"exampleFix":"// before: repeating a rebase from an already-completed root\nedit.rebase(root_of_finished_rebase, /* repeat */ true, ...)?;\n// after: verify the root is pending, else do a fresh rebase\nlet commit = repo.find_commit(root_id)?.decode()?.into_owned()?;\nlet repeat = gix_tix::edit::rebase::is_pending(&commit);\nedit.rebase(root_id, repeat, ...)?;","handlingStrategy":"validation","validationCode":"let commit = repo.find_commit(root_id)?.decode()?.into_owned()?;\nif !gix_tix::edit::rebase::is_pending(&commit) {\n    // either don't set repeat, or re-establish the pending state first\n}\n","typeGuard":"fn is_repeatable_root(repo: &gix::Repository, id: ObjectId) -> anyhow::Result<bool> {\n    Ok(gix_tix::edit::rebase::is_pending(&repo.find_commit(id)?.decode()?.into_owned()?))\n}\n","tryCatchPattern":null,"preventionTips":["Check `is_pending` on the rebase root before any repeated edit","Complete or abort pending rebases before running follow-up edits","Never reuse root ids captured before a prior rebase — re-resolve them"],"tags":["rebase","git","state-validation"],"backgroundTag":"invalid-state-transition","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}