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

  1. Recompute the graph and derive fresh edge selectors immediately before calling integrate_branch_with_steps
  2. Re-run the branch integration from the current workspace state rather than replaying cached steps
  3. 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

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


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 when

View on GitHub (pinned to 58e5313667)