{"record":{"id":"9f15d931128dd5f9","repo":"gitbutlerapp/gitbutler","slug":"expected-selector-for-step-to-refer-to-a-commit","errorCode":null,"errorMessage":"Expected selector for {step:?} to refer to a commit","messagePattern":"Expected selector for (.+?) to refer to a commit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/graph_rebase/mod.rs","lineNumber":221,"sourceCode":"///\n/// Hash, PartialEq, and Eq are implemented for this struct. Because selectors\n/// are a pointer to a node in a particular version of the Editor's internal\n/// representation, it means that you can have two selectors that when\n/// normalised point to the same node. If you want to ensure you have just one\n/// selector to a given node, make sure you are working with selectors all\n/// normalised to the latest revision of the Editor.\n#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]\npub struct Selector {\n    id: StepGraphIndex,\n    revision: usize,\n}\n\nimpl ToCommitSelector for Selector {\n    fn to_commit_selector(&self, editor: &Editor<impl RefMetadata>) -> Result<Selector> {\n        let selector = editor.history.normalize_selector(*self)?;\n        let step = &editor.graph[selector.id];\n        if !matches!(step, Step::Pick(_)) {\n            bail!(\"Expected selector for {step:?} to refer to a commit\");\n        }\n\n        Ok(selector)\n    }\n}\n\nimpl ToReferenceSelector for Selector {\n    fn to_reference_selector(&self, editor: &Editor<impl RefMetadata>) -> Result<Selector> {\n        let selector = editor.history.normalize_selector(*self)?;\n        let step = &editor.graph[selector.id];\n        if !matches!(step, Step::Reference { .. }) {\n            bail!(\"Expected selector for {step:?} to refer to a reference\");\n        }\n\n        Ok(selector)\n    }\n}\n","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-rebase/src/graph_rebase/mod.rs#L203-L239","documentation":"ToCommitSelector::to_commit_selector normalizes a Selector against the editor's history and asserts that the graph node it points to is a Step::Pick (a commit). If the normalized selector resolves to any other step kind (e.g. a Step::Reference), the requested conversion is impossible and the library bails.","triggerScenarios":"Passing a Selector that resolves to a reference/other non-pick step into any API taking impl ToCommitSelector — e.g. calling to_commit_selector on a selector obtained for a branch/reference step, or an id that after normalize_selector lands on a non-Pick node.","commonSituations":"Mixing up selectors for references and commits when scripting graph edits (move_branch vs commit operations); using a stale selector index after the graph was mutated so normalization resolves elsewhere.","solutions":["Confirm the selector points at a Pick step before calling to_commit_selector (inspect editor.graph[selector.id])","Use to_reference_selector instead if the selector names a reference","Re-obtain the selector from the current editor state after graph mutations"],"exampleFix":"// before: selector names a branch -> error\nlet commit = selector.to_commit_selector(&editor)?;\n// after\nlet step = &editor.graph[selector.id];\nlet commit = match step {\n    Step::Pick(_) => selector.to_commit_selector(&editor)?,\n    Step::Reference { .. } => bail!(\"use a commit selector here\"),\n    _ => bail!(\"unsupported step\"),\n};","handlingStrategy":"type-guard","validationCode":"let step = &editor.graph[selector.id];\nif !matches!(step, Step::Pick(_)) { return Err(anyhow!(\"not a commit selector\")); }","typeGuard":"fn is_pick(selector: Selector, editor: &Editor<impl RefMetadata>) -> bool {\n    matches!(editor.graph[selector.id], Step::Pick(_))\n}","tryCatchPattern":"match selector.to_commit_selector(&editor) {\n    Ok(commit) => commit,\n    Err(_) => bail!(\"selector does not refer to a commit; check step kind first\"),\n}","preventionTips":["Track which selectors name commits vs references","Re-normalize selectors after every graph mutation"],"tags":["rebase","selector","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"}