gitbutlerapp/gitbutler · error

Failed to apply branch: {outcome}

Error message

Failed to apply branch: {outcome}

What it means

In the status TUI's stack-mode apply flow (crates/but/src/command/legacy/status/tui/app/stack_mode.rs:406), apply::run returning ApplyOutcome::ConflictAborted(outcome) is converted to a hard error. The abort means applying the selected branch onto the current workspace would produce merge conflicts, so the operation was rolled back without touching the worktree; the outcome detail lists what conflicted.

Source

Thrown at crates/but/src/command/legacy/status/tui/app/stack_mode.rs:406

            b.has_local
                .cmp(&a.has_local)
                .then_with(|| b.updated_at.cmp(&a.updated_at))
                .then_with(|| a.name.cmp(&b.name))
        });

        let Some(items) = NonEmpty::from_vec(branches) else {
            return Ok(());
        };
        let picker = FuzzyPicker::new(items, self.theme, |item, ctx, messages| {
            let branch = {
                let repo = ctx.repo.get()?;
                BranchArg(item.name.clone()).resolve_legacy_top_level_apply_branch_name(&repo)?
            };

            let mut guard = ctx.exclusive_worktree_access();
            match apply::run(ctx, guard.write_permission(), ApplyOperation { branch })? {
                ApplyOutcome::ConflictAborted(outcome) => {
                    anyhow::bail!("Failed to apply branch: {outcome}")
                }
                ApplyOutcome::AlreadyApplied { .. } | ApplyOutcome::Applied { .. } => {}
            }

            messages.extend([
                Message::EnterNormalModeAfterConfirmingOperation,
                Message::Reload(
                    Some(SelectAfterReload::Branch(item.name)),
                    ReloadCause::Mutation,
                ),
            ]);

            Ok(())
        });
        self.modal = Some(Modal::ApplyStackPicker {
            picker: Box::new(picker),
            key_binds: fuzzy_picker_key_binds(),
        });

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Read the conflict detail in the outcome message to identify the clashing files, then unapply the conflicting stack and apply branches in an order that avoids the overlap.
  2. Update/rebase the branch onto the current target so it applies cleanly, then retry.
  3. Move the conflicting commits to a separate stack or apply the branch in a dedicated worktree.

Example fix

# before: stacks 'auth' and 'db' both edit schema.sql
# stack-mode -> apply 'db'  ->  Failed to apply branch: conflict...

# after
but branch unapply auth   # or move conflicting commits
# then apply 'db', then re-apply 'auth' resolving order
Defensive patterns

Strategy: try-catch

Try / catch

match apply::run(ctx, guard.write_permission(), ApplyOperation { branch })? {
    ApplyOutcome::ConflictAborted(outcome) => {
        // surface outcome (conflicting files), suggest unapply/reorder, keep worktree untouched
        Err(anyhow::anyhow!("Failed to apply branch: {outcome}"))
    }
    ApplyOutcome::AlreadyApplied { .. } | ApplyOutcome::Applied { .. } => Ok(()),
}

Prevention

When it happens

Trigger: Applying a branch via the stack-mode fuzzy picker when its changes conflict with already-applied workspace branches — overlapping edits to the same files or hunks.

Common situations: Two stacks editing the same lines; applying a branch forked before recent workspace changes; stale branches that need rebasing onto the target.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/63dace1935d1f7b8. Report an issue: GitHub.