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

  1. Build the parent set from the graph itself: enumerate outgoing edges of `target.parent` (what validation uses) and pick from those
  2. Refresh the editor/graph and recompute selectors immediately before calling disconnect
  3. 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

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


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/5200bccda263bbd8. Report an issue: GitHub.