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

  1. Reload the workspace and confirm the stack still lists at least one branch segment via stack_details
  2. Re-apply or recreate a branch in that stack, or unassign the file so default routing applies
  3. 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

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


AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17). Data as JSON: /api/errors/06a2edc81d83df8b. Report an issue: GitHub.