gitbutlerapp/gitbutler · error
Stack has no branches
Error message
Stack has no branches
What it means
In ensure_target_commit() priority 2: the candidate hunk is assigned to a stack (candidate.stack_id is Some), but that stack's details contain zero branch_details, so find_target_branch() — which falls back to branch_details.first() — finds no branch and there is no reference to insert a blank commit below. With any branch present this error cannot fire, even when branch_ref does not match.
Source
Thrown at crates/but-api/src/legacy/absorb.rs:442
candidate.hunk.path
);
}
}
// Priority 2: Use the candidate's stack ID if available
if let Some(stack_id) = candidate.stack_id {
let branch_ref = candidate.branch_ref.as_ref();
let stack_details = crate::legacy::workspace::stack_details(ctx, Some(stack_id))?;
if let Some(branch) = find_target_branch(&stack_details, branch_ref)
&& let Some(commit) = branch.commits.first()
{
return Ok((stack_id, commit.id, AbsorptionReason::StackAssignment));
}
// If there are no commits in the target branch, create a blank commit first
let branch = find_target_branch(&stack_details, branch_ref)
.ok_or_else(|| anyhow::anyhow!("Stack has no branches"))?;
commit_insert_blank_only_impl(
ctx,
RelativeTo::Reference(branch.reference.clone()),
InsertSide::Below,
DryRun::No,
perm,
)?;
// Fetch again to get the newly created commit
let stack_details = crate::legacy::workspace::stack_details(ctx, Some(stack_id))?;
if let Some(branch) = find_target_branch(&stack_details, branch_ref)
&& let Some(commit) = branch.commits.first()
{
return Ok((stack_id, commit.id, AbsorptionReason::StackAssignment));
}
anyhow::bail!("Failed to create blank commit in stack: {stack_id:?}");
}View on GitHub (pinned to 2497b8007a)
Solutions
- Reload the workspace and confirm the stack still lists at least one branch segment via stack_details
- Re-apply or recreate a branch in that stack, or unassign the file so default routing applies
- If the metadata is inconsistent, use GitButler workspace verification/repair or undo to a consistent oplog entry
Defensive patterns
Strategy: validation
Validate before calling
let details = workspace_stack_details(ctx, stack_id)?;
if details.branch_details.is_empty() {
// stack cannot absorb: ask the user to re-apply a branch or unassign the file
} else {
let plan = absorption_plan_with_perm(ctx, target, perm)?;
} Type guard
fn stack_has_branches(details: &StackDetails) -> bool {
!details.branch_details.is_empty()
} Prevention
- Check stack_details for the assigned stack before offering absorb on its files
- Unassign files when their stack's last branch is unapplied or deleted
- Treat empty branch_details as invalid workspace state and repair it early
When it happens
Trigger: absorption_plan/absorb with a hunk assigned to a stack whose branch_details are empty: all segments anonymous or unapplied, or the stack was emptied while the file-assignment metadata persisted.
Common situations: All branches of the stack were unapplied or deleted while assignments to it remained; workspace metadata partially written or out of sync; another writer mutated the workspace between listing and absorbing.
Related errors
- Unable to determine target commit for unassigned change: {}
- Branch not found: {branch_name}
- Stack has no ID
- No uncommitted changes assigned to branch: {branch_name}
- No uncommitted changes found for the selected files
AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17).
Data as JSON: /api/errors/06a2edc81d83df8b.
Report an issue: GitHub.