{"record":{"id":"3350537f6efe15c1","repo":"gitbutlerapp/gitbutler","slug":"a-matching-parent-can-t-be-found-in-the-output-graph","errorCode":null,"errorMessage":"A matching parent can't be found in the output graph","messagePattern":"A matching parent can't be found in the output graph","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/graph_rebase/rebase.rs","lineNumber":48,"sourceCode":"        for step_idx in steps_to_pick {\n            // Do the frikkin rebase man!\n            let step = self.graph[step_idx].clone();\n            let new_idx = match step {\n                Step::Pick(pick) if !pick.mutable => {\n                    // Immutable picks are copied verbatim: the commit keeps its\n                    // id, so there's no cherry-pick to run and nothing to record\n                    // in the history mapping.\n                    output_graph.add_node(Step::Pick(pick))\n                }\n                Step::Pick(pick) => {\n                    let graph_parents = collect_ordered_parents(&self.graph, step_idx);\n                    let ontos = match pick.preserved_parents.clone() {\n                        Some(ontos) => ontos,\n                        None => graph_parents\n                            .iter()\n                            .map(|idx| {\n                                let Some(new_idx) = graph_mapping.get(idx) else {\n                                    bail!(\"A matching parent can't be found in the output graph\");\n                                };\n\n                                match output_graph[*new_idx] {\n                                    Step::Pick(Pick { id, .. }) => Ok(id),\n                                    _ => bail!(\"A parent in the output graph is not a pick\"),\n                                }\n                            })\n                            .collect::<Result<Vec<_>>>()?,\n                    };\n\n                    let outcome = cherry_pick(\n                        &self.repo,\n                        pick.id,\n                        &ontos,\n                        pick.pick_mode,\n                        pick.tree_merge_mode,\n                        pick.sign_commit,\n                    )?;","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-rebase/src/graph_rebase/rebase.rs#L30-L66","documentation":"During rebase, a pick's parents are mapped from the input graph to the output graph via graph_mapping. When a pick has no preserved_parents, each graph parent must map to a node in the output graph; an unmapped index means the new parentage cannot be computed, so the rebase bails rather than guessing parents.","triggerScenarios":"Calling rebase (public) when an input-graph parent index of a pick is absent from graph_mapping — typically because that parent node was dropped/filtered from the output graph (e.g. an ancestor pick removed) while descendants still reference it.","commonSituations":"Dropping or filtering out parent commits from the rebase plan while children still depend on them; custom step transformations that remove nodes without remapping descendant parentage; bugs in callers building the output graph.","solutions":["Ensure all parents of kept picks are also present in the output graph (don't drop ancestors of kept commits)","Provide preserved_parents explicitly for picks whose parent mapping you control","Recompute graph_mapping after any node removals before running rebase"],"exampleFix":"// before: parent dropped from output graph\noutput_graph.drop(parent_selector)?;\nrebase(&graph, &output_graph)?;\n// after: keep ancestors or remap children first\nlet mapped = graph_mapping.get(&parent_idx)\n    .context(\"parent missing; re-add or remap before rebase\")?;\nrebase(&graph, &output_graph)?;","handlingStrategy":"validation","validationCode":"for idx in graph_parents {\n    if !graph_mapping.contains_key(&idx) {\n        return Err(anyhow!(\"parent {} missing from output graph\", idx));\n    }\n}","typeGuard":"fn parents_mapped(graph_parents: &[usize], mapping: &HashMap<usize, usize>) -> bool {\n    graph_parents.iter().all(|p| mapping.contains_key(p))\n}","tryCatchPattern":"let new_idx = graph_mapping.get(&idx)\n    .ok_or_else(|| anyhow!(\"parent dropped from output graph; re-add or set preserved_parents\"))?;","preventionTips":["Never drop ancestor picks while keeping their descendants","Set preserved_parents explicitly for picks with custom parentage","Recompute the graph mapping after any output-graph node removal"],"tags":["rebase","graph","parents","mapping"],"backgroundTag":"resource-not-found","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}