gitbutlerapp/gitbutler · error

A parent in the output graph is not a pick

Error message

A parent in the output graph is not a pick

What it means

During graph-based rebase output reconstruction, a step's parent index was remapped into the output graph, but the node at the new index is not a Pick step (e.g. a Reference or marker node). The rebase machinery requires every parent of a cherry-picked commit in the output graph to be an actual picked commit carrying a commit id. This indicates the output graph structure diverged from the invariants the rebase algorithm maintains.

Solutions

  1. Inspect the rebase steps: ensure reference steps are ordered so they never become the parent of a pick in the output graph.
  2. Verify the graph_mapping/output_graph construction for recent changes to but-rebase; this is an invariant violation, likely an internal bug — report with the failing step list.
  3. Reconstruct the rebase plan without reference steps in parent positions and retry.
Defensive patterns

Strategy: validation

Validate before calling

fn all_parents_are_picks(steps: &[RebaseStep]) -> bool {
    // references must never precede a pick that depends on them as a parent
    !steps.iter().zip(steps.iter().skip(1)).any(|(prev, next)| {
        matches!(prev, RebaseStep::Reference(_)) && matches!(next, RebaseStep::Pick(_))
    })
}

Prevention

When it happens

Trigger: Calling the rebase operation when graph_mapping maps a step's parent to an output-graph node that is a non-Pick Step variant — typically a Reference step or internal marker node becoming the parent of a pick.

Common situations: Rebases involving virtual branch reference steps interleaved with picks; bugs or regressions in graph construction when references are re-parented; corrupted or hand-edited branch graphs.

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 gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/40c5d89558fec095. Report an issue: GitHub.

Appendix: source

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

                    // Immutable picks are copied verbatim: the commit keeps its
                    // id, so there's no cherry-pick to run and nothing to record
                    // in the history mapping.
                    output_graph.add_node(Step::Pick(pick))
                }
                Step::Pick(pick) => {
                    let graph_parents = collect_ordered_parents(&self.graph, step_idx);
                    let ontos = match pick.preserved_parents.clone() {
                        Some(ontos) => ontos,
                        None => graph_parents
                            .iter()
                            .map(|idx| {
                                let Some(new_idx) = graph_mapping.get(idx) else {
                                    bail!("A matching parent can't be found in the output graph");
                                };

                                match output_graph[*new_idx] {
                                    Step::Pick(Pick { id, .. }) => Ok(id),
                                    _ => bail!("A parent in the output graph is not a pick"),
                                }
                            })
                            .collect::<Result<Vec<_>>>()?,
                    };

                    let outcome = cherry_pick(
                        &self.repo,
                        pick.id,
                        &ontos,
                        pick.pick_mode,
                        pick.tree_merge_mode,
                        pick.sign_commit,
                    )?;

                    if matches!(outcome, CherryPickOutcome::ConflictedCommit(_))
                        && !pick.conflictable
                    {
                        bail!(

View on GitHub (pinned to 58e5313667)