gitbutlerapp/gitbutler · error
Selected edge endpoint wasn't found among direct neighbors
Error message
Selected edge endpoint wasn't found among direct neighbors
What it means
When reordering/integrating branches, edge selectors must refer to endpoints that are direct neighbors in the current commit graph. If a selected selector is not found among the available neighbor candidates, the selection is invalid for the current graph state and the function bails.
Solutions
- Recompute the graph and derive fresh edge selectors immediately before calling integrate_branch_with_steps
- Re-run the branch integration from the current workspace state rather than replaying cached steps
- Check that the target branch/commit is still a direct neighbor of the intended anchor in the current stack
Example fix
// before let steps = load_cached_steps(); // selectors from old graph integrate_branch_with_steps(editor, steps)?; // after let steps = compute_steps_from_current_graph(editor)?; integrate_branch_with_steps(editor, steps)?;
Defensive patterns
Strategy: validation
Validate before calling
let available = current_neighbor_edges(editor)?;
if !steps.iter().all(|s| available.contains(&s.endpoint)) {
steps = recompute_steps(editor)?;
} Try / catch
match result {
Err(e) if e.to_string().contains("direct neighbors") => {
// recompute selectors from the current graph and retry
}
other => other?,
} Prevention
- Recompute edge selectors immediately before graph manipulation
- Invalidate cached steps after any operation that rewrites history
- Serialize the graph version alongside saved selectors and compare before use
When it happens
Trigger: Calling integrate_branch_with_steps with edge selectors computed against an older graph topology (after commits were moved, rebased, or removed), so the selector's endpoint is no longer a direct neighbor.
Common situations: Stale UI selections after another operation reshaped the stack; concurrent modifications to the workspace between selection and integration; hardcoded/serialized selectors reused across sessions.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Failed to extract described changes from source commit
- Failed to find corresponding segment for
- Some selected changes no longer match the worktree's…
- stale pre-commit index backup at
- Tearing off a branch requires a workspace common base
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/51f78f86410c628b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-workspace/src/graph_manipulation.rs:236
edge_selection: EdgeSelection,
) -> Result<Vec<(Selector, usize)>> {
let available = match edge_selection {
EdgeSelection::Children => editor.direct_children(target)?,
EdgeSelection::Parents => editor.direct_parents(target)?,
};
match selectors {
SelectorSet::All => Ok(available),
SelectorSet::None => Ok(Vec::new()),
SelectorSet::Some(some_selectors) => {
let mut selected = Vec::new();
for selector in some_selectors.as_slice() {
let selector = selector.to_selector(editor)?;
let Some((_, order)) = available
.iter()
.find(|(candidate, _)| *candidate == selector)
else {
bail!("Selected edge endpoint wasn't found among direct neighbors")
};
selected.push((selector, *order));
}
Ok(selected)
}
}
}
/// Reconnect a rebuilt segment to previously selected children and parents.
///
/// `editor` is the mutable graph editor whose edges will be recreated.
///
/// `delimiter` identifies the rebuilt segment's child-most and parent-most
/// selectors.
///
/// `children` are the previously captured child edges that should point back to
/// `delimiter.child`. If the child is already connected to `delimiter.child`, no
/// new edge is added. Otherwise, the original edge order is reused whenView on GitHub (pinned to 58e5313667)