{"record":{"id":"471ef708a694bd06","repo":"gitbutlerapp/gitbutler","slug":"couldn-t-find-branch-to-move-in-workspace-with-ref","errorCode":null,"errorMessage":"Couldn't find branch to move in workspace with reference name: {subject_branch_name}","messagePattern":"Couldn't find branch to move in workspace with reference name: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/branch/move_branch.rs","lineNumber":67,"sourceCode":"    /// `workspace` - Used for getting the surrounding context of the branch being torn off.\n    ///     In the future, we should not rely on the projection and do it fully on the graph.\n    ///\n    /// `subject_branch_name` - The branch to take out of a stack.\n    ///\n    /// `stack_id_override` - Optionally, the ID to use for the newly created stack.\n    ///     Mainly used for testing purposes.\n    ///\n    /// Returns the in memory update [outcome](Outcome) that can then used for materialisation.\n    pub fn tear_off_branch<'ws, 'meta, M: RefMetadata>(\n        editor: Editor<'ws, 'meta, M>,\n        subject_branch_name: &FullNameRef,\n        stack_id_override: Option<StackId>,\n    ) -> anyhow::Result<Outcome<'ws, 'meta, M>> {\n        let successful_rebase = editor.rebase()?;\n        let workspace = successful_rebase.overlayed_graph()?.into_workspace()?;\n        let mut editor = successful_rebase.into_editor();\n        let Some(source) = workspace.find_segment_and_stack_by_refname(subject_branch_name) else {\n            bail!(\n                \"Couldn't find branch to move in workspace with reference name: {subject_branch_name}\"\n            );\n        };\n\n        // We're currently stopping the move branch operations imperatively at this stage, in order to\n        // reduce the scope of this first iteration of moving the branches.\n        // TODO: Enable and test that we can move branches in any kind of workspace.\n        match &workspace.kind {\n            WorkspaceKind::Managed { .. } => {}\n            WorkspaceKind::ManagedMissingWorkspaceCommit { .. } => {\n                bail!(\"Moving branches currently need a workspace commit\")\n            }\n            WorkspaceKind::AdHoc => {\n                bail!(\"Moving branches in non-managed workspaces is not supported\");\n            }\n        };\n\n        let mut ws_meta = workspace.metadata.clone();","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-workspace/src/branch/move_branch.rs#L49-L85","documentation":"`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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Must resolve to a workspace segment before moving:\nlet workspace = /* current but_graph::Workspace */;\nif workspace.find_segment_and_stack_by_refname(subject_branch_name).is_none() {\n    anyhow::bail!(\"branch {subject_branch_name} is not a stack segment in this workspace; refresh the workspace graph or add the branch first\");\n}","typeGuard":"fn branch_is_moveable(ws: &but_graph::Workspace, name: &gix::refs::FullNameRef) -> bool {\n    ws.find_segment_and_stack_by_refname(name).is_some() && matches!(ws.kind, but_graph::WorkspaceKind::Managed { .. })\n}","tryCatchPattern":"if let Err(err) = move_branch::tear_off_branch(editor, &subject_branch_name, stack_override) {\n    if err.to_string().contains(\"Couldn't find branch to move\") {\n        // refresh workspace graph and re-check the branch list; likely stale or unmanaged branch\n    }\n}","preventionTips":["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)."],"tags":["rust","git","but-workspace","move-branch","precondition","ref-not-found"],"backgroundTag":"branch-not-in-workspace","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}