{"record":{"id":"46e8652088015a06","repo":"gitbutlerapp/gitbutler","slug":"invalid-parents-to-disconnect-selectorset-none-i","errorCode":null,"errorMessage":"Invalid parents to disconnect: SelectorSet::None is not allowed","messagePattern":"Invalid parents to disconnect: SelectorSet::None is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/graph_rebase/mutate.rs","lineNumber":409,"sourceCode":"            SelectorSet::Some(children) => Some(\n                children\n                    .as_slice()\n                    .iter()\n                    .map(|from_child| from_child.to_selector(self))\n                    .collect::<Result<Vec<_>>>()?\n                    .into_iter()\n                    .map(|selector| self.history.normalize_selector(selector))\n                    .collect::<Result<Vec<_>>>()?,\n            ),\n        };\n\n        let parents_to_disconnect = match parents_to_disconnect {\n            SelectorSet::All => None,\n            SelectorSet::None => {\n                if skip_reconnect_step {\n                    Some(Vec::new())\n                } else {\n                    return Err(anyhow!(\n                        \"Invalid parents to disconnect: SelectorSet::None is not allowed\"\n                    ));\n                }\n            }\n            SelectorSet::Some(parents) => Some(\n                parents\n                    .as_slice()\n                    .iter()\n                    .map(|from_parent| from_parent.to_selector(self))\n                    .collect::<Result<Vec<_>>>()?\n                    .into_iter()\n                    .map(|selector| self.history.normalize_selector(selector))\n                    .collect::<Result<Vec<_>>>()?,\n            ),\n        };\n\n        // Edges to children.\n        let incoming_edges = self","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-rebase/src/graph_rebase/mutate.rs#L391-L427","documentation":"`Editor::disconnect_segment_from` documents (and enforces) that `parents_to_disconnect = SelectorSet::None` is only legal when `skip_reconnect_step` is true. With None-parents and reconnection enabled, every disconnected child would need to be reconnected to an empty parent set — an ill-defined operation — so the editor rejects the combination up front.","triggerScenarios":"Calling `disconnect_segment_from(target, children, SelectorSet::None, false)` — i.e. disconnecting children while specifying no parents to reconnect them to, without opting out of the reconnect step.","commonSituations":"Callers translating a UI action like 'detach these children only' into editor calls without realizing the default contract; porting code from an older signature where None had different semantics.","solutions":["If you really want to disconnect with no parents and no reconnection, pass `skip_reconnect_step = true`","If children should be reattached, specify the parents explicitly with `SelectorSet::Some(SomeSelectors::new([...])?)`","To disconnect from everything, use `SelectorSet::All`","Re-read the doc comment on `disconnect_segment_from` — the error conditions are enumerated there verbatim"],"exampleFix":"// before\neditor.disconnect_segment_from(target, children, SelectorSet::None, /* skip_reconnect_step */ false)?; // Err\n\n// after — pick the intended contract:\neditor.disconnect_segment_from(target, children, SelectorSet::None, true)?; // no reconnect\n// or\neditor.disconnect_segment_from(target, children, SelectorSet::Some(SomeSelectors::new(parents)?), false)?; // reconnect to explicit parents","handlingStrategy":"validation","validationCode":"// Mirror the documented contract before calling:\nif matches!(parents_to_disconnect, SelectorSet::None) {\n    anyhow::ensure!(skip_reconnect_step,\n        \"SelectorSet::None parents requires skip_reconnect_step = true\");\n}\neditor.disconnect_segment_from(target, children, parents_to_disconnect, skip_reconnect_step)?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Encode the contract once in a wrapper that maps (parents, skip_reconnect) combinations","Write unit tests covering None/All/Some parent combinations so invalid ones never reach the editor","Read the doc comment on disconnect_segment_from; the error conditions are listed verbatim"],"tags":["rust","graph-rebase","api-contract","validation","git"],"backgroundTag":"invalid-argument-combination","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}