{"record":{"id":"f9793a6db58e220f","repo":"gitbutlerapp/gitbutler","slug":"reference-target-in-rebase-result-is-not-a-commit","errorCode":null,"errorMessage":"Reference target in rebase result is not a commit","messagePattern":"Reference target in rebase result is not a commit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/graph_rebase/mod.rs","lineNumber":407,"sourceCode":"    /// Return the commit targeted by `ref_name` in the post-rebase step graph.\n    pub fn reference_target(&self, ref_name: &gix::refs::FullNameRef) -> Result<gix::ObjectId> {\n        let reference = self\n            .graph\n            .node_indices()\n            .find(|node| {\n                matches!(\n                    &self.graph[*node],\n                    Step::Reference { refname, .. } if refname == ref_name\n                )\n            })\n            .with_context(|| format!(\"Could not find reference '{ref_name}' in rebase result\"))?;\n        let parent = collect_ordered_parents(&self.graph, reference)\n            .into_iter()\n            .next()\n            .context(\"Reference has no target commit in rebase result\")?;\n        match self.graph[parent] {\n            Step::Pick(Pick { id, .. }) => Ok(id),\n            _ => bail!(\"Reference target in rebase result is not a commit\"),\n        }\n    }\n\n    /// Returns a preview of what the but-graph will look like after\n    /// materialization.\n    ///\n    /// Any objects referenced in the resulting graph must be accessed via the\n    /// in-memory repository owned by this [`SuccessfulRebase`] (`self.repo`),\n    /// since they might exist only in memory.\n    pub fn overlayed_graph(&self) -> Result<but_graph::Graph> {\n        self.overlayed_graph_with_workspace_overrides(None, None)\n    }\n\n    /// Return the post-rebase graph with optional ad-hoc workspace projection overrides.\n    ///\n    /// This is useful for dry-run operations whose graph rewrite is accompanied by metadata or\n    /// checkout changes that are deliberately not persisted. The override entrypoint must name the\n    /// commit and local reference that would be checked out, while `branch_stack_order` supplies the","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-rebase/src/graph_rebase/mod.rs#L389-L425","documentation":"reference_target finds the first ordered parent of a reference step in the materialized result graph and expects that parent node to be a Step::Pick whose commit is the ref's target. If the parent exists but is not a Pick, the ref target cannot be expressed as a commit id and the library bails.","triggerScenarios":"Calling reference_target (e.g. via move_branch_in_single_branch_mode) on a reference whose first parent in the result graph is not a Pick step — for instance the ref hangs off a special/root step or another Reference node instead of a commit.","commonSituations":"Moving a branch onto a position in the graph where the nearest parent is another reference or a non-commit step; querying the target of a freshly added reference that has not been attached to a commit yet.","solutions":["Ensure the reference is a child of a Pick (commit) step before querying its target","Attach or move the reference so its parent is a commit pick in the graph","Use lookup_reference if you only need the ref name, not its target commit"],"exampleFix":"// before\nlet target = editor.reference_target(branch_selector)?; // parent isn't a Pick\n// after\nlet parents = collect_ordered_parents(&editor.graph, branch_selector);\nif parents.iter().any(|p| !matches!(editor.graph[*p], Step::Pick(_))) {\n    // first move the branch under a commit pick\n}\nlet target = editor.reference_target(branch_selector)?;","handlingStrategy":"validation","validationCode":"let parent = collect_ordered_parents(&editor.graph, reference).into_iter().next()\n    .ok_or_else(|| anyhow!(\"reference has no parent\"))?;\nif !matches!(editor.graph[parent], Step::Pick(_)) { return Err(anyhow!(\"parent is not a pick\")); }","typeGuard":"fn parent_is_pick(graph: &Graph, reference: Selector) -> bool {\n    collect_ordered_parents(graph, reference).first()\n        .map(|p| matches!(graph[*p], Step::Pick(_)))\n        .unwrap_or(false)\n}","tryCatchPattern":"match editor.reference_target(sel) {\n    Ok(id) => id,\n    Err(_) => { /* move the reference under a commit pick, then retry */ }\n}","preventionTips":["Only query targets of references attached to commit picks","Move references before mutating their parents"],"tags":["rebase","graph","reference","type-mismatch"],"backgroundTag":"type-mismatch","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"}