gitbutlerapp/gitbutler · error · anyhow::Error
Cannot move branch {subject_branch_name} onto itself
Error message
Cannot move branch {subject_branch_name} onto itself What it means
move_branch refuses when the subject and target reference names are identical, because moving a branch onto itself is a no-op at best and a graph-corrupting cycle at worst. It is a pure argument-validation error raised before any rebase or traversal runs, so no repository state is touched.
Source
Thrown at crates/but-workspace/src/branch/move_branch.rs:186
/// `editor` is assumed to have been generated from the given `workspace`
/// and therefore aligned.
///
/// `workspace` - Used for getting the surrounding context of the branch being moved.
/// In the future, we should not rely on the projection and do it fully on the graph.
///
/// `subject_branch_name` is the full reference name of the branch to move.
///
/// `target_branch_name` is the full reference name of the branch to move the subject
/// branch on top of.
///
/// Returns an [outcome](Outcome) for potential materialisation.
pub fn move_branch<'ws, 'meta, M: RefMetadata>(
editor: Editor<'ws, 'meta, M>,
subject_branch_name: &FullNameRef,
target_branch_name: &FullNameRef,
) -> anyhow::Result<Outcome<'ws, 'meta, M>> {
if subject_branch_name == target_branch_name {
bail!("Cannot move branch {subject_branch_name} onto itself");
}
let successful_rebase = editor.rebase()?;
let workspace = successful_rebase.overlayed_graph()?.into_workspace()?;
let (source, destination) =
retrieve_branches_and_containers(&workspace, subject_branch_name, target_branch_name)?;
// Each kind of workspace has a very different notion of what "moving a branch" means, so we
// dispatch into a dedicated handler for each one.
match &workspace.kind {
WorkspaceKind::AdHoc => move_branch_in_single_branch_mode(
successful_rebase,
workspace,
source,
destination,
subject_branch_name,
target_branch_name,View on GitHub (pinned to caf1f223d3)
Solutions
- Skip the call when subject_branch_name == target_branch_name (treat it as a no-op success in the UI layer).
- Fix the caller so the drop target is a different branch than the dragged one.
- If names come from user input, validate they differ before resolving them to full ref names.
Example fix
// before
move_branch(editor, subject_branch_name, target_branch_name)?;
// after
if subject_branch_name == target_branch_name {
return Ok(outcome_noop()); // nothing to move
}
move_branch(editor, subject_branch_name, target_branch_name)?; Defensive patterns
Strategy: validation
Validate before calling
if subject_branch_name == target_branch_name {
// no-op: treat as success without calling the API
return Ok(default_outcome());
} Prevention
- Compare subject and target ref names before every move call.
- In drag-and-drop UIs, ignore drops where source row == target row.
- Log both names when refusing, to catch caller mapping bugs early.
When it happens
Trigger: Calling but_workspace::branch::move_branch(editor, name, name) with the same FullNameRef for subject and target, e.g. because a UI passed the dragged row as both source and destination.
Common situations: Drag-and-drop UI bugs where a branch is dropped onto itself; refactored callers that accidentally reuse one variable for both parameters; fuzzy branch-name matching that resolves two different user inputs to the same full ref name.
Related errors
- Invalid message format
- HTTP Error ${response.statusText}: ${text}
- Tearing off a branch requires a workspace common base
- 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/cb2604d6e38da547.
Report an issue: GitHub.