gitbutlerapp/gitbutler · error

Cannot order selected commits by parentage: selected commit

Error message

Cannot order selected commits by parentage: selected commit {} could not be ranked from editor graph nodes

What it means

order_commit_selectors_by_parentage ranks selected commits topologically using the editor's step graph. Every selected commit must be rankable from graph nodes; if one is missing from the computed rank map, ordering would silently drop it, so the library bails to preserve the Result contract.

Solutions

  1. Ensure every selected commit exists as a Pick node in the current editor graph
  2. Rebuild the editor from the current history so the graph includes all selected commits
  3. Filter selected commits down to ids present in the graph before ordering

Example fix

// before
let ordered = editor.order_commit_selectors_by_parentage(&selected)?; // stale id
// after
let selected: Vec<_> = selected.into_iter()
    .filter(|c| editor.lookup_step(Selector::from(c.id)).is_ok())
    .collect();
let ordered = editor.order_commit_selectors_by_parentage(&selected)?;
Defensive patterns

Strategy: validation

Validate before calling

let rank = step_graph_parent_to_child_rank(editor, &selected_ids)?;
if selected.iter().any(|c| !rank.contains_key(&c.id)) { return Err(anyhow!("unrankable selection")); }

Type guard

fn all_rankable(selected: &[Commit], rank: &HashMap<StepGraphRank, ()>) -> bool {
    selected.iter().all(|c| rank.contains_key(&c.id))
}

Prevention

When it happens

Trigger: Calling order_commit_selectors_by_parentage (e.g. via prepare_squash_step_for_editor) with a selected commit whose ObjectId has no corresponding rankable node — the commit is not represented in the editor graph (never picked, dropped, or from another history).

Common situations: Squash selections containing commits not part of the current rebase; ids captured before history was rewritten; passing raw object ids from the repo instead of ids present as picks in the editor graph.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/cb6b224ff8591d0d. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-rebase/src/graph_rebase/ordering.rs:57

            }
        }

        if selected.len() <= 1 {
            return Ok(selected.into_iter().map(|s| s.selector).collect());
        }

        // Build a deterministic rank from editor step-graph order.
        let selected_ids = selected
            .iter()
            .map(|commit| commit.id)
            .collect::<HashSet<_>>();
        let step_graph_rank = step_graph_parent_to_child_rank(self, &selected_ids)?;

        // Preserve the Result contract: unreachable selected commits are a runtime error,
        // not an internal panic.
        for commit in &selected {
            if !step_graph_rank.contains_key(&commit.id) {
                bail!(
                    "Cannot order selected commits by parentage: selected commit {} could not be ranked from editor graph nodes",
                    commit.id
                );
            }
        }

        // The rank map is the sole source of truth for deterministic parent-before-child ordering.
        selected.sort_by_key(|commit| {
            let rank = step_graph_rank
                .get(&commit.id)
                .copied()
                .unwrap_or(usize::MAX);
            (rank, commit.input_order)
        });

        Ok(selected.into_iter().map(|s| s.selector).collect())
    }
}

View on GitHub (pinned to 58e5313667)