gitbutlerapp/gitbutler · error · anyhow::Error
Tearing off a branch requires a workspace common base
Error message
Tearing off a branch requires a workspace common base
What it means
Thrown by the tear-off path of move_branch in a managed workspace when the workspace has no lower-bound segment carrying a ref name. The lower bound ref (the workspace's common base/target branch) is what the torn-off branch gets re-parented onto, so without it the disconnect operation has no anchor target to select in the graph. It signals a workspace whose base stack is anonymous or missing rather than a bad API call.
Source
Thrown at crates/but-workspace/src/branch/move_branch.rs:111
ws_meta,
new_tip: None,
branch_stack_order: None,
});
}
let Some(workspace_head) = workspace.tip_commit().map(|commit| commit.id) else {
bail!("Couldn't find workspace head.")
};
let head_selector = editor
.select_commit(workspace_head)
.context("Failed to find the workspace head in the graph.")?;
let Some(lower_bound_ref) = workspace
.lower_bound_segment_id
.map(|segment_id| &workspace.graph[segment_id])
.and_then(|segment| segment.ref_name())
else {
bail!("Tearing off a branch requires a workspace common base");
};
let target_selector = editor
.select_reference(lower_bound_ref)
.context("Failed to find target reference in graph.")?;
let DisconnectParameters {
delimiter: subject_delimiter,
children_to_disconnect,
parents_to_disconnect,
} = get_disconnect_parameters(
&editor,
source_stack,
subject_segment,
Some(workspace_head),
)?;
editor.disconnect_segment_from(View on GitHub (pinned to caf1f223d3)
Solutions
- Set (or restore) a target/base branch for the workspace in GitButler settings and re-sync, so the workspace has a named lower bound segment.
- Verify workspace.lower_bound_segment_id maps to a segment whose ref_name() is Some(...) before invoking the tear-off move.
- If the base ref was deleted, recreate it (e.g. from the remote tracking ref) and re-traverse the workspace.
Example fix
// before
let outcome = but_workspace::branch::move_branch(editor, &subject, &target)?;
// after
let ws = successful_rebase.overlayed_graph()?.into_workspace()?;
ensure!(
ws.lower_bound_segment_id
.and_then(|id| ws.graph[id].ref_name())
.is_some(),
"workspace has no common base ref; set a target branch first"
);
let outcome = but_workspace::branch::move_branch(editor, &subject, &target)?; Defensive patterns
Strategy: validation
Validate before calling
let ws = successful_rebase.overlayed_graph()?.into_workspace()?;
let has_base_ref = ws
.lower_bound_segment_id
.map(|id| &ws.graph[id])
.and_then(|segment| segment.ref_name())
.is_some();
if !has_base_ref {
// set a target branch for the workspace before tearing off
return Ok(None);
} Try / catch
match move_branch(editor, &subject, &target) {
Ok(outcome) => { /* ... */ }
Err(err) if err.to_string().contains("workspace common base") => {
// prompt user to pick a target branch for the workspace
}
Err(err) => return Err(err),
} Prevention
- Always configure a target/base branch before offering tear-off moves.
- After deleting a base ref, re-sync the workspace before further moves.
- In batch automation, skip tear-off when the workspace lower bound has no ref name.
When it happens
Trigger: Calling move_branch's tear-off flow when workspace.lower_bound_segment_id is None, or when the segment at that index has no ref_name() (an anonymous base segment). This happens for workspaces built on detached-HEAD bases or local-only commits with no target branch ref.
Common situations: Workspace created while HEAD was detached or on commits with no base branch; workspace whose target ref was deleted or never synced; repositories where the user never picked a target branch in GitButler settings.
Related errors
- When using OpenRouter, you must provide a valid API key
- HTTP Error ${response.statusText}: ${text}
- Cannot move branch {subject_branch_name} onto itself
- Moving a non-empty branch in single-branch mode is not yet s
- Couldn't find target branch to move in workspace with refere
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/10fa60ad00f8beac.
Report an issue: GitHub.