{"record":{"id":"256b42c1d9945447","repo":"gitbutlerapp/gitbutler","slug":"branchnotfound","errorCode":"BranchNotFound","errorMessage":"branch with ID {stack_id} not found","messagePattern":"branch with ID (.+?) not found","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/legacy/virtual_branches.rs","lineNumber":306,"sourceCode":"    }\n\n    Ok(())\n}\n\nfn apply_stack_order_updates(\n    workspace: &mut but_core::ref_metadata::Workspace,\n    updates: Vec<BranchUpdateRequest>,\n) -> Result<bool> {\n    let mut requested_orders = HashMap::new();\n\n    for update in updates {\n        let stack_id = update.id.context(\"BUG(opt-stack-id)\")?;\n        if !workspace\n            .stacks\n            .iter()\n            .any(|stack| stack.id == stack_id && stack.is_in_workspace())\n        {\n            return Err(anyhow!(\"branch with ID {stack_id} not found\")\n                .context(but_error::Code::BranchNotFound));\n        }\n\n        if let Some(order) = update.order {\n            requested_orders.insert(stack_id, order);\n        }\n    }\n\n    if requested_orders.is_empty() {\n        return Ok(false);\n    }\n\n    let original_stack_ids = workspace\n        .stacks\n        .iter()\n        .map(|stack| stack.id)\n        .collect::<Vec<_>>();\n    let original_orders = original_stack_ids","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-api/src/legacy/virtual_branches.rs#L288-L324","documentation":"`apply_stack_order_updates` processes requested stack order changes; for each update it requires a stack with that id to exist AND be in the workspace (`is_in_workspace()`). Otherwise it throws \"branch with ID {stack_id} not found\" with code `BranchNotFound`. The id came from the caller's update list, so it references a stack that is missing or unapplied.","triggerScenarios":"Calling update_stack_order (reorder) with a StackId that is not in the workspace — unapplied stack, deleted stack, stale id from an outdated workspace snapshot; also reached via stack_order_updates_reject_unapplied_stacks which intentionally rejects unapplied stacks.","commonSituations":"Drag-and-drop UI reordering a stale list while another pane unapplied the stack; automation using ids from an old `but` output; concurrent modifications to workspace order.","solutions":["Re-fetch the current workspace stack list and use only ids that are currently applied/in-workspace.","Remove the stale id from your update list and retry with the refreshed ids.","Re-apply the stack to the workspace first if reordering an unapplied branch is intended.","Avoid concurrent workspace mutations while submitting order updates."],"exampleFix":"// before\nlet ids = cached_stack_ids; // may include unapplied stacks\nupdate_stack_order(ctx, ids.iter().enumerate().map(|(i, id)| Update { id: Some(*id), order: Some(i as u32), .. }));\n// after\nlet ws = ctx.workspace()?; // fresh state\nlet ids: Vec<_> = ws.stacks.iter().filter(|s| s.is_in_workspace()).map(|s| s.id.unwrap()).collect();\nupdate_stack_order(ctx, ids.iter().enumerate().map(|(i, id)| Update { id: Some(*id), order: Some(i as u32), .. }));","handlingStrategy":"validation","validationCode":"// only submit order updates for stacks currently in the workspace\nlet ws = ctx.workspace()?;\nlet valid: Vec<_> = updates.into_iter()\n    .filter(|u| u.id.map(|id| ws.stacks.iter().any(|s| s.id == Some(id) && s.is_in_workspace())).unwrap_or(true))\n    .collect();","typeGuard":"fn is_in_workspace(stacks: &[Stack], id: StackId) -> bool {\n    stacks.iter().any(|s| s.id == Some(id) && s.is_in_workspace())\n}","tryCatchPattern":"match update_stack_order(ctx, updates) {\n    Err(e) if e.to_string().contains(\"BranchNotFound\") => {\n        let ws = ctx.workspace()?; // refresh and retry with current ids\n        update_stack_order(ctx, refresh_ids(ws, updates))?;\n    }\n    other => other?,\n}","preventionTips":["Build reorder requests only from a freshly read workspace stack list","Filter to stacks where is_in_workspace() is true","Serialize concurrent workspace mutations (reorder + unapply)"],"tags":["git","stack-not-found","workspace","ordering"],"backgroundTag":"resource-not-found","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}