gitbutlerapp/gitbutler · error · anyhow::Error
Couldn't find branch to move in workspace with reference nam
Error message
Couldn't find branch to move in workspace with reference name: {subject_branch_name} What it means
`tear_off_branch` (move_branch.rs) bails when `workspace.find_segment_and_stack_by_refname(subject_branch_name)` finds no stack segment for the given reference name — the branch to move is not part of the current GitButler workspace graph. The lookup happens on the overlayed workspace after `editor.rebase()`, so the name must match a segment ref exactly.
Source
Thrown at crates/but-workspace/src/branch/move_branch.rs:67
/// `workspace` - Used for getting the surrounding context of the branch being torn off.
/// In the future, we should not rely on the projection and do it fully on the graph.
///
/// `subject_branch_name` - The branch to take out of a stack.
///
/// `stack_id_override` - Optionally, the ID to use for the newly created stack.
/// Mainly used for testing purposes.
///
/// Returns the in memory update [outcome](Outcome) that can then used for materialisation.
pub fn tear_off_branch<'ws, 'meta, M: RefMetadata>(
editor: Editor<'ws, 'meta, M>,
subject_branch_name: &FullNameRef,
stack_id_override: Option<StackId>,
) -> anyhow::Result<Outcome<'ws, 'meta, M>> {
let successful_rebase = editor.rebase()?;
let workspace = successful_rebase.overlayed_graph()?.into_workspace()?;
let mut editor = successful_rebase.into_editor();
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}"
);
};
// We're currently stopping the move branch operations imperatively at this stage, in order to
// reduce the scope of this first iteration of moving the branches.
// TODO: Enable and test that we can move branches in any kind of workspace.
match &workspace.kind {
WorkspaceKind::Managed { .. } => {}
WorkspaceKind::ManagedMissingWorkspaceCommit { .. } => {
bail!("Moving branches currently need a workspace commit")
}
WorkspaceKind::AdHoc => {
bail!("Moving branches in non-managed workspaces is not supported");
}
};
let mut ws_meta = workspace.metadata.clone();View on GitHub (pinned to caf1f223d3)
Solutions
- Verify the branch is a workspace stack segment first: `workspace.find_segment_and_stack_by_refname(name).is_some()`; if not, refresh/rebuild the workspace graph before retrying.
- Pass the full reference name (`refs/heads/...`) exactly as segments store it — check `segment.ref_name()`.
- If the branch lives outside the workspace, add it to the workspace (apply/adopt) before moving.
- If it was deleted concurrently, re-sync the UI list from the current workspace and drop the stale request.
Defensive patterns
Strategy: validation
Validate before calling
// Must resolve to a workspace segment before moving:
let workspace = /* current but_graph::Workspace */;
if workspace.find_segment_and_stack_by_refname(subject_branch_name).is_none() {
anyhow::bail!("branch {subject_branch_name} is not a stack segment in this workspace; refresh the workspace graph or add the branch first");
} Type guard
fn branch_is_moveable(ws: &but_graph::Workspace, name: &gix::refs::FullNameRef) -> bool {
ws.find_segment_and_stack_by_refname(name).is_some() && matches!(ws.kind, but_graph::WorkspaceKind::Managed { .. })
} Try / catch
if let Err(err) = move_branch::tear_off_branch(editor, &subject_branch_name, stack_override) {
if err.to_string().contains("Couldn't find branch to move") {
// refresh workspace graph and re-check the branch list; likely stale or unmanaged branch
}
} Prevention
- Always check find_segment_and_stack_by_refname before offering 'move branch' in the UI.
- Pass the exact full ref name stored on segments.
- Refresh the workspace graph after external git operations (branch create/delete/rename).
When it happens
Trigger: Calling the move-branch API with a ref name that is not a segment in the workspace: an unmanaged local branch, a remote tracking ref, a typo'd/partial name, or a branch that was deleted/renamed between the UI listing and the call. Also stale workspace data (graph built before the branch was added).
Common situations: Trying to move a branch that was never adopted into the workspace; racing with a concurrent branch deletion/rename; passing `refs/heads/x` vs `x` inconsistently; workspace cache out of date after external git operations.
Related errors
- Integration steps cannot be empty
- Squash step must have at least two commits
- Moving branches currently need a workspace commit
- Moving branches in non-managed workspaces is not supported
- Couldn't find workspace head.
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/471ef708a694bd06.
Report an issue: GitHub.