gitbutlerapp/gitbutler · error

Couldn't find target branch to move in workspace with refere

Error message

Couldn't find target branch to move in workspace with reference name: {target_branch_name}

What it means

The destination counterpart of the subject lookup: find_segment_and_stack_by_refname found the branch to move but not the target ref name it should be moved onto. The move is refused before any mutation because there is no destination stack/segment to operate on.

Source

Thrown at crates/but-workspace/src/branch/move_branch.rs:505

    ///
    /// ### What the future holds
    /// In the future, where we're not afraid of complex graphs, we've figured out UX and data wrangling,
    /// the concept of a segment might not hold, and hence we'll have to figure out a better way of determining
    /// what to cut (e.g. letting the clients decide what to cut).
    fn retrieve_branches_and_containers(
        workspace: &but_graph::Workspace,
        subject_branch_name: &FullNameRef,
        target_branch_name: &FullNameRef,
    ) -> anyhow::Result<(WorkspaceSegmentContext, WorkspaceSegmentContext)> {
        let Some(source) = workspace.find_segment_and_stack_by_refname(subject_branch_name) else {
            bail!(
                "Couldn't find branch to move in workspace with reference name: {subject_branch_name}"
            );
        };

        let Some(destination) = workspace.find_segment_and_stack_by_refname(target_branch_name)
        else {
            bail!(
                "Couldn't find target branch to move in workspace with reference name: {target_branch_name}"
            );
        };
        Ok((own_context(source), own_context(destination)))
    }

    /// Reorder `subject` to sit directly on top of `target` in the tip-to-base ad-hoc `order`.
    ///
    /// Mirrors the [`Position::Above`](crate::branch::create_reference::Position) case of
    /// `create_reference`'s `insert_into_branch_stack_order`: `subject` is removed and re-inserted
    /// at `target`'s slot, pushing `target` (and everything below it) down.
    ///
    /// If `target` isn't tracked yet (stale or empty metadata) it is appended first, so that a move
    /// where *both* branches are missing adds them both - `subject` on top of `target` - instead of
    /// silently clobbering the rest of the ordering down to just `subject`.
    fn reorder_branch_in_stack_order(
        mut order: Vec<gix::refs::FullName>,
        target_branch_name: &FullNameRef,

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Pass fully-qualified ref names for the target as well (refs/heads/<branch>).
  2. Validate the target is an applied branch in the current workspace before enabling the move action.
  3. Refresh the workspace and retry if the target was removed by a concurrent client.

Example fix

// before
move_branch(editor, subject, target)?; // target may be gone

// after
let (src, dst) = (
    ws.find_segment_and_stack_by_refname(subject),
    ws.find_segment_and_stack_by_refname(target),
);
ensure!(src.is_some() && dst.is_some(), "both branches must be applied in the workspace");
move_branch(editor, subject, target)?;
Defensive patterns

Strategy: validation

Validate before calling

let ws = successful_rebase.overlayed_graph()?.into_workspace()?;
if ws.find_segment_and_stack_by_refname(target_branch_name).is_none() {
    // target no longer applied; refresh the list and let the user re-pick
    return refresh_branch_list();
}

Type guard

fn target_in_workspace(ws: &but_graph::Workspace, name: &FullNameRef) -> bool {
    ws.find_segment_and_stack_by_refname(name).is_some()
}

Try / catch

match move_branch(editor, &subject, &target) {
    Err(err) if err.to_string().contains("Couldn't find target branch") => {
        ui::error("The drop target is no longer available");
        Ok(default_outcome())
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling move_branch where target_branch_name is not a segment ref in the workspace projection — unapplied target, deleted branch, or a short name instead of a full refs/heads/... name.

Common situations: Drop target deleted between UI render and the API call; target branch name taken from user input without validation; short-vs-full ref name mismatch.

Related errors


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