{"record":{"id":"2c16dc693160af00","repo":"gitbutlerapp/gitbutler","slug":"failed-to-find-commit-commit-id-in-rebase-editor","errorCode":null,"errorMessage":"Failed to find commit {commit_id} in rebase editor","messagePattern":"Failed to find commit (.+?) in rebase editor","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/graph_rebase/merge_commit_changes.rs","lineNumber":141,"sourceCode":"        subject_commit_ids: Vec<gix::ObjectId>,\n    ) -> Result<Vec<PlannedCommitChange>> {\n        self.try_select_commit(target_commit_id).with_context(|| {\n            format!(\"Failed to find commit {target_commit_id} in rebase editor\")\n        })?;\n        let selected_commit_ids = deduplicate_commit_ids(subject_commit_ids);\n        if selected_commit_ids.is_empty() {\n            return Ok(Vec::new());\n        }\n\n        let selected_commit_set = selected_commit_ids.iter().copied().collect::<HashSet<_>>();\n        let traversal = traverse_graph_for_planning(self, target_commit_id, &selected_commit_set)?;\n\n        for commit_id in &selected_commit_ids {\n            if !traversal\n                .first_parent_metadata_by_selected_commit_id\n                .contains_key(commit_id)\n            {\n                bail!(\"Failed to find commit {commit_id} in rebase editor\");\n            }\n        }\n\n        // A map from selected commit ID to how many child commits it has that\n        // are also selected.\n        let mut selected_child_count = HashMap::<gix::ObjectId, usize>::with_capacity(\n            traversal.ordered_selected_commit_ids.len(),\n        );\n        for commit_id in traversal.ordered_selected_commit_ids.iter().copied() {\n            selected_child_count.insert(commit_id, 0);\n        }\n        for selected_parent_id in traversal\n            .first_parent_metadata_by_selected_commit_id\n            .values()\n            .filter_map(|metadata| metadata.selected_first_parent_id)\n        {\n            if let Some(child_count) = selected_child_count.get_mut(&selected_parent_id) {\n                *child_count += 1;","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-rebase/src/graph_rebase/merge_commit_changes.rs#L123-L159","documentation":"When planning tree changes for a merge commit, every selected commit id must have first-parent metadata recorded by the rebase editor traversal. If a selected commit id is absent from that map, the traversal never saw it, so its changes cannot be attributed; the library bails rather than silently dropping the commit's changes.","triggerScenarios":"Calling merge_commit_changes_to_tree (which calls plan_commit_changes_for_merge) with a selected_commit_ids entry that is not a first-parent commit known to the editor's traversal — e.g. a commit outside the merge's first-parent history, a stale ObjectId, or an id from a different graph.","commonSituations":"Passing commit ids captured from a previous rebase session after the history was rewritten; selecting commits from a side branch that aren't on the merge's first-parent chain; id mismatch after re-creating the editor.","solutions":["Verify each selected commit id belongs to the merge's first-parent history in the current editor traversal","Re-create the traversal/editor so first_parent_metadata_by_selected_commit_id is rebuilt from the current history","Remove stale or foreign commit ids from selected_commit_ids"],"exampleFix":"// before\nlet selected = vec![old_commit_id]; // not in current traversal\nmerge_commit_changes_to_tree(editor, &selected)?;\n// after\nlet selected: Vec<_> = current_traversal.selected_commit_ids().collect();\nmerge_commit_changes_to_tree(editor, &selected)?;","handlingStrategy":"validation","validationCode":"let known: HashSet<_> = traversal.first_parent_metadata_by_selected_commit_id.keys().copied().collect();\nassert!(selected.iter().all(|c| known.contains(&c.into())), \"selected commit not in traversal\");","typeGuard":"fn all_selected_known(selected: &[gix::ObjectId], meta: &HashMap<gix::ObjectId, FirstParentMetadata>) -> bool {\n    selected.iter().all(|id| meta.contains_key(id))\n}","tryCatchPattern":null,"preventionTips":["Always derive selected commit ids from the same traversal that feeds the merge planner","Never reuse ids from previous rebase sessions","Validate ids against the current history before planning"],"tags":["git","rebase","merge","lookup"],"backgroundTag":"record-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"}