gitbutlerapp/gitbutler · error

Failed to find corresponding parent

Error message

Failed to find corresponding parent

What it means

After rebuilding each node in the output graph, the algorithm re-adds edges to its parents using graph_mapping to translate old parent node indices to new ones. If a parent's target index is missing from graph_mapping, the corresponding output parent does not exist and the edge cannot be rewired, so the rebase aborts. This means a commit was rewritten into the output graph while its parent was not.

Solutions

  1. Ensure every parent commit of each step is included in the rebase plan or its ancestors are fully mapped.
  2. Rebuild the step list so no commit's parent is excluded while the commit itself is kept.
  3. If triggered by a but-rebase bug, report with the failing step sequence.
Defensive patterns

Strategy: validation

Validate before calling

// Every kept commit's parents must also be kept (or be ancestors of base)
fn parents_covered(steps: &[RebaseStep]) -> bool {
    let kept: std::collections::HashSet<_> = steps.iter().filter_map(|s| match s {
        RebaseStep::Pick(p) => Some(p.commit_id), _ => None }).collect();
    steps.iter().all(|s| match s {
        RebaseStep::Pick(p) => p.parent_ids.iter().all(|pp| kept.contains(pp)), _ => true })
}

Prevention

When it happens

Trigger: Rebase where an edge target node was never mapped into the output graph — e.g. a parent step was skipped, pruned, or the mapping insertion failed for that node.

Common situations: Partial rebases dropping commits that are still referenced as parents; internal graph-construction bugs; plans assembled manually with dangling parent references.

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/594c70c6881c5fb3. Report an issue: GitHub.

Appendix: source

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

                    }

                    output_graph.add_node(Step::Reference { refname, mutable })
                }
                Step::None => output_graph.add_node(Step::None),
            };

            graph_mapping.insert(step_idx, new_idx);

            let mut edges = self
                .graph
                .edges_directed(step_idx, petgraph::Direction::Outgoing)
                .collect::<Vec<_>>();
            edges.sort_by_key(|e| e.weight().order);
            edges.reverse();

            for e in edges {
                let Some(new_parent) = graph_mapping.get(&e.target()) else {
                    bail!("Failed to find corresponding parent");
                };

                output_graph.add_edge(new_idx, *new_parent, e.weight().clone());
            }
        }

        // Find deleted references. `initial_references` only contains mutable
        // references, so immutable references are never considered for deletion.
        for reference in self.initial_references.iter() {
            if !ref_edits.iter().any(|e| e.name == *reference)
                && !unchanged_references.iter().any(|e| e == reference)
            {
                ref_edits.push(RefEdit::delete(reference.clone(), PreviousValue::MustExist));
            }
        }

        history.add_revision(graph_mapping);

View on GitHub (pinned to 58e5313667)