{"record":{"id":"858c9f228e4b9feb","repo":"gitbutlerapp/gitbutler","slug":"refusing-to-delete-last-named-segment-as-it-w","errorCode":null,"errorMessage":"Refusing to delete last named segment '{}' as it would leave an anonymous segment","messagePattern":"Refusing to delete last named segment '(.+?)' as it would leave an anonymous segment","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/but-workspace/src/branch/remove_reference.rs","lineNumber":56,"sourceCode":"    let Some((stack, _segment)) = workspace.find_segment_and_stack_by_refname(ref_name) else {\n        return Ok(None);\n    };\n\n    if avoid_anonymous_stacks\n        && (stack\n            .segments\n            .iter()\n            .map(|s| s.commits.len())\n            .sum::<usize>()\n            > 0\n            && stack\n                .segments\n                .iter()\n                .filter(|s| s.ref_info.is_some())\n                .count()\n                < 2)\n    {\n        bail!(\n            \"Refusing to delete last named segment '{}' as it would leave an anonymous segment\",\n            ref_name.shorten()\n        );\n    }\n\n    let deleted_ref = if let Some(r) = repo.try_find_reference(ref_name)? {\n        let safe = but_core::branch::SafeDelete::new(repo)?;\n        let out = safe.delete_reference(&r)?;\n        if let Some(paths) = out.checked_out_in_worktree_dirs {\n            bail_precondition!(\n                \"Refusing to delete a branch that is checked out. Worktrees are: {paths:?}\"\n            );\n        }\n        true\n    } else {\n        false\n    };\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-workspace/src/branch/remove_reference.rs#L38-L74","documentation":"remove_reference refuses to delete the last named segment of a stack that owns commits, because doing so would leave those commits in an anonymous segment with no ref — invisible/unattributable in the workspace UI. The guard fires only when the stack has commits and fewer than two named segments remain after the deletion.","triggerScenarios":"Calling remove_reference on the only ref-bearing segment of a stack whose segments total more than zero commits (e.g. deleting the sole branch of a stack that has work on it).","commonSituations":"Trying to delete the last branch of a workspace stack directly via git ref deletion instead of unapply; cleanup scripts iterating over refs hitting a stack's only named branch.","solutions":["Use the workspace unapply operation instead — it moves commits and disposes of the workspace representation correctly.","Move the commits to another branch (or integrate them) first, then delete the now-empty ref.","Delete a different, non-last named segment if the goal is just pruning."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let named_segments = stack.segments.iter().filter(|s| s.ref_info.is_some()).count();\nlet total_commits: usize = stack.segments.iter().map(|s| s.commits.len()).sum();\nif total_commits > 0 && named_segments < 2 {\n    // deleting the last named segment would orphan its commits: use unapply instead\n    return route_to_unapply(ref_name);\n}","typeGuard":null,"tryCatchPattern":"match remove_reference(repo, meta, ref_name, &stack) {\n    Err(err) if err.to_string().contains(\"last named segment\") => {\n        unapply(repo, meta, &ws, ref_name, Options::default())\n    }\n    other => other,\n}","preventionTips":["Route 'delete last branch of a stack' actions to unapply, not raw ref deletion.","Check named-segment count and commit totals before deleting refs programmatically.","Teach users that branches with commits must be unapplied, not deleted."],"tags":["gitbutler","delete-branch","workspace","safety-guard","rust"],"backgroundTag":"last-named-branch-deletion-guard","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}