{"record":{"id":"29f9074580e42a9a","repo":"gitbutlerapp/gitbutler","slug":"branch-not-found-branch-name","errorCode":null,"errorMessage":"Branch not found: {branch_name}","messagePattern":"Branch not found: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/legacy/absorb.rs","lineNumber":152,"sourceCode":"                ChangesSource::Head,\n                true,\n                perm.read_permission(),\n            )?;\n            let all_assignments = worktree_changes.assignments;\n            let dependencies = worktree_changes.dependencies;\n\n            // Get the stack ID for this branch\n            let stacks = crate::legacy::workspace::stacks(ctx, None)?;\n\n            // Find the stack that contains this branch\n            let stack = stacks\n                .iter()\n                .find(|s| {\n                    s.heads\n                        .iter()\n                        .any(|h| h.name.to_str().map(|n| n == branch_name).unwrap_or(false))\n                })\n                .ok_or_else(|| anyhow::anyhow!(\"Branch not found: {branch_name}\"))?;\n\n            let stack_id = stack.id.ok_or_else(|| anyhow::anyhow!(\"Stack has no ID\"))?;\n\n            // Filter assignments to just this stack\n            let candidates: Vec<AbsorbCandidate> = all_assignments\n                .into_iter()\n                .filter(|a| a.stack_id == Some(stack_id))\n                .map(Into::into)\n                .collect();\n\n            if candidates.is_empty() {\n                anyhow::bail!(\"No uncommitted changes assigned to branch: {branch_name}\");\n            }\n\n            (candidates, dependencies)\n        }\n        AbsorptionTarget::TreeChanges {\n            changes,","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/crates/but-api/src/legacy/absorb.rs#L134-L170","documentation":"absorption_plan_with_perm with AbsorptionTarget::Branch scans the workspace's stacks for one whose heads include the given branch name (exact short-name comparison) and bails 'Branch not found' when no stack contains it. The plan needs the owning stack's ID to filter hunk assignments, so a branch outside the current stacks cannot be targeted.","triggerScenarios":"Calling absorb/absorption_plan with branch_name that is not a head of any current stack — typos, branches belonging to unapplied or archived stacks, remote-only names, or full refnames instead of short names.","commonSituations":"Absorbing into a branch whose stack was unapplied; passing origin/<name>; stale UI state after a branch rename; scripts reusing old branch names.","solutions":["List current stack heads (`but status` / the workspace stacks API) and pass the exact branch name.","Re-apply the stack containing the branch, then retry.","If absorbing loose file changes, prefer the TreeChanges target with an explicit file selection instead of a branch target."],"exampleFix":"// Rust caller: validate before planning\nlet stacks = workspace::stacks(ctx, None)?;\nlet is_head = stacks.iter().any(|s| {\n    s.heads.iter().any(|h| h.name.to_str() == Some(branch_name.as_str()))\n});\nanyhow::ensure!(is_head, \"branch {branch_name} is not an applied stack head\");\nlet plan = absorption_plan_with_perm(ctx, AbsorptionTarget::Branch { branch_name }, perm)?;","handlingStrategy":"validation","validationCode":"fn branch_is_stack_head(stacks: &[Stack], branch: &str) -> bool {\n    stacks.iter().any(|s| {\n        s.heads\n            .iter()\n            .any(|h| h.name.to_str().map(|n| n == branch).unwrap_or(false))\n    })\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Populate absorb target pickers from live stack heads only.","Re-check names after renames or unapplies before planning absorption.","Use short names, never full refnames or remote-prefixed names."],"tags":["absorb","branch-not-found","stacks","workspace"],"backgroundTag":"branch-not-found","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}