{"record":{"id":"1386dec7a36c1ade","repo":"gitbutlerapp/gitbutler","slug":"invalid-parent-delimitation-requested-child-is-no","errorCode":null,"errorMessage":"Invalid parent delimitation: requested child is not a direct parent of target.child","messagePattern":"Invalid parent delimitation: requested child is not a direct parent of target\\.child","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/graph_rebase/mutate.rs","lineNumber":464,"sourceCode":"            .iter()\n            .map(|(_, _, edge_source)| *edge_source)\n            .collect::<HashSet<_>>();\n\n        // 1. Verify that all parents and children to disconnect are directly connected to the target segment.\n        if let Some(parents_to_disconnect) = parents_to_disconnect.as_ref() {\n            for selector in parents_to_disconnect {\n                if !available_parents.contains(&selector.id) {\n                    return Err(anyhow!(\n                        \"Invalid parent delimitation: requested parent is not a direct parent of target.parent\"\n                    ));\n                }\n            }\n        }\n\n        if let Some(children_to_disconnect) = children_to_disconnect.as_ref() {\n            for selector in children_to_disconnect {\n                if !available_children.contains(&selector.id) {\n                    return Err(anyhow!(\n                        \"Invalid parent delimitation: requested child is not a direct parent of target.child\"\n                    ));\n                }\n            }\n        }\n\n        let parent_ids_to_disconnect = parents_to_disconnect\n            .as_ref()\n            .map(|parents| parents.iter().map(|s| s.id).collect::<HashSet<_>>());\n        let child_ids_to_disconnect = children_to_disconnect\n            .as_ref()\n            .map(|children| children.iter().map(|s| s.id).collect::<HashSet<_>>());\n\n        let mut disconnected_parent_edges = Vec::new();\n        // 2. Disconnect parents.\n        for (edge_id, edge_weight, edge_target) in outgoing_edges {\n            let should_disconnect = parent_ids_to_disconnect\n                .as_ref()","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-rebase/src/graph_rebase/mutate.rs#L446-L482","documentation":"`Editor::disconnect_segment_from` validates that every selector in `children_to_disconnect` appears among the incoming edges of `target.child`; this error means a selected 'child' is not directly adjacent. Note the message text is wrong in the source: it says the child \"is not a direct parent of target.child\" — a copy-paste from the parent case — but the check is against direct children. Trust the condition, not the wording.","triggerScenarios":"Passing a grandchild, a commit on another lane, or a stale id in `children_to_disconnect`; selectors computed from an outdated graph snapshot whose incoming edges differ.","commonSituations":"UI multi-select including non-adjacent commits as 'children'; concurrent graph edits between computing selectors and disconnecting; tests with fixtures whose topology changed.","solutions":["Enumerate incoming edges of `target.child` and select children only from that set","Recompute selectors from the live editor graph right before the call","Fix upstream (optional): correct the message to 'requested child is not a direct child of target.child' to avoid future confusion"],"exampleFix":"// before\nlet children = SelectorSet::Some(SomeSelectors::new(user_selected)?); // may include non-adjacent ids\neditor.disconnect_segment_from(target, children, parents, false)?; // Err\n\n// after — derive children from the graph's actual edges\nlet adjacent: Vec<AnySelector> = graph\n    .edges_directed(target_child_id, petgraph::Direction::Incoming)\n    .map(|e| AnySelector::Commit(e.source().attach(repo)))\n    .collect();\nlet children = SelectorSet::Some(SomeSelectors::new(adjacent)?);","handlingStrategy":"validation","validationCode":"// Restrict candidate children to nodes directly connected to target.child:\nlet adjacent: Vec<_> = graph\n    .edges_directed(target_child_id, petgraph::Direction::Incoming)\n    .map(|e| e.source())\n    .collect();\nanyhow::ensure!(\n    requested_children.iter().all(|c| adjacent.contains(c)),\n    \"non-adjacent child requested\"\n);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Note the error text mislabels the check ('direct parent of target.child') — the code validates direct children","Build children sets from incoming edges of target.child only","Refresh the editor graph before computing selectors in interactive flows"],"tags":["rust","graph-rebase","git","topology","validation","error-message-bug"],"backgroundTag":"graph-topology-violation","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}