gitbutlerapp/gitbutler · error
Invalid parent delimitation: requested parent is not a direc
Error message
Invalid parent delimitation: requested parent is not a direct parent of target.parent
What it means
`Editor::disconnect_segment_from` validates that every selector in `parents_to_disconnect` is directly connected to `target.parent` (it must appear among the outgoing edges of `target.parent` in the segment graph). A selector that names an existing but non-adjacent commit fails this check — 'direct parent' means adjacent in the current graph topology, not just any ancestor.
Source
Thrown at crates/but-rebase/src/graph_rebase/mutate.rs:454
.edges_directed(target_parent.id, Direction::Outgoing)
.map(|e| (e.id(), e.weight().to_owned(), e.target()))
.collect::<Vec<_>>();
// All available parents
let available_parents = outgoing_edges
.iter()
.map(|(_, _, edge_target)| *edge_target)
.collect::<HashSet<_>>();
let available_children = incoming_edges
.iter()
.map(|(_, _, edge_source)| *edge_source)
.collect::<HashSet<_>>();
// 1. Verify that all parents and children to disconnect are directly connected to the target segment.
if let Some(parents_to_disconnect) = parents_to_disconnect.as_ref() {
for selector in parents_to_disconnect {
if !available_parents.contains(&selector.id) {
return Err(anyhow!(
"Invalid parent delimitation: requested parent is not a direct parent of target.parent"
));
}
}
}
if let Some(children_to_disconnect) = children_to_disconnect.as_ref() {
for selector in children_to_disconnect {
if !available_children.contains(&selector.id) {
return Err(anyhow!(
"Invalid parent delimitation: requested child is not a direct parent of target.child"
));
}
}
}
let parent_ids_to_disconnect = parents_to_disconnect
.as_ref()View on GitHub (pinned to caf1f223d3)
Solutions
- Build the parent set from the graph itself: enumerate outgoing edges of `target.parent` (what validation uses) and pick from those
- Refresh the editor/graph and recompute selectors immediately before calling disconnect
- If the intent is a deeper disconnect, perform multiple adjacent `disconnect_segment_from` calls instead of one non-adjacent one
Example fix
// before
let parents = SelectorSet::Some(SomeSelectors::new(user_selected_commits)?); // may include non-adjacent ids
editor.disconnect_segment_from(target, children, parents, false)?; // Err
// after — derive parents from the graph's actual edges
let adjacent: Vec<AnySelector> = graph
.edges_directed(target_parent_id, petgraph::Direction::Outgoing)
.map(|e| AnySelector::Commit(e.target().attach(repo)))
.collect();
let parents = SelectorSet::Some(SomeSelectors::new(adjacent)?); Defensive patterns
Strategy: validation
Validate before calling
// Restrict candidate parents to nodes directly connected to target.parent:
let adjacent: Vec<_> = graph
.edges_directed(target_parent_id, petgraph::Direction::Outgoing)
.map(|e| e.target())
.collect();
anyhow::ensure!(
requested_parents.iter().all(|p| adjacent.contains(p)),
"non-adjacent parent requested"
); Prevention
- Derive disconnect sets from graph edges, never from user selection or ancestry walks
- Compute selectors and perform the disconnect in one pass over a single graph snapshot
- Snapshot-test graph surgery operations so topology assumptions are pinned
When it happens
Trigger: Passing a grandparent, sibling, or a commit from another stack as a parent to disconnect; selectors computed against an older graph snapshot whose edges have since changed; normalizing selectors against a different target than the one used for validation.
Common situations: Callers deriving disconnect sets from user multi-select (easy to include non-adjacent commits); graph mutated between selector computation and the disconnect call; porting graph surgery logic that assumed ancestry rather than adjacency.
Related errors
- Invalid parent delimitation: requested child is not a direct
- Invalid parents to disconnect: SelectorSet::None is not allo
- Invalid message format
- HTTP Error ${response.statusText}: ${text}
- Invalid section for global key: {key}
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/5200bccda263bbd8.
Report an issue: GitHub.