gitbutlerapp/gitbutler · info

Land cancelled

Error message

Land cancelled

What it means

This error is raised by `confirm_direct_target_update` in the `but merge` CLI command when the user answers 'No' to the interactive confirmation prompt asking whether to land a branch (and optionally everything below it) directly onto the target branch. It is a deliberate, user-initiated abort, not a failure: the operation is cancelled before any refs are moved or anything is pushed. It exists so the landing is never performed without explicit consent when running interactively without `--yes`.

Solutions

  1. Re-run the command and answer 'Yes' (the default) at the confirmation prompt if the landing is intended.
  2. Add the `--yes` flag to skip interactive confirmation: `but merge <branch-id> --yes` (only when certain of the target).
  3. Use `--whole-stack` only intentionally; if the prompt showed unwanted extras, land a single branch instead by omitting `--whole-stack`.
  4. Verify the target with `but branch list` / `but base` if the displayed target was unexpected, then retry.

Example fix

// before: interactive run cancelled by user
but merge branch-abc
# Land branch-abc directly onto origin/main? [Y/n] n
// after: explicit non-interactive confirmation
but merge branch-abc --yes
Defensive patterns

Strategy: try-catch

Validate before calling

// Scripting: skip the interactive prompt entirely by passing --yes,
// or pre-check that the command will prompt:
// `but merge <id> --yes` avoids this error in non-interactive runs.
const args = hasConfirmed ? ['merge', branchId, '--yes'] : ['merge', branchId];

Try / catch

try {
  runBut(['merge', branchId]);
} catch (e) {
  if (e.stderr.includes('Land cancelled')) {
    // user declined; treat as a no-op, not a failure
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `but merge <branch-id>` (without `--yes`) in a terminal and answering 'No' (or pressing a key that maps to No) at the prompt 'Land <branch> directly onto <remote>/<target>?' or 'Land <branch> and everything below it directly onto <remote>/<target>?'. The prompt is reached only when `extras` (extra branches below) may be affected and the output channel supports terminal input.

Common situations: A developer inspects the prompt, notices the landing would affect more branches than expected (extras listed in the warning above the prompt), and declines. A user changes their mind after seeing the target display name is the wrong remote/branch. Scripting/automation runs the command attached to a TTY without `--yes` and an automated answer of 'No' is fed in.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/b24bc9453899411e. Report an issue: GitHub.

Appendix: source

Thrown at crates/but/src/command/legacy/merge/messaging.rs:242

    }

    if yes {
        return Ok(());
    }

    let Some(mut inout) = out.prepare_for_terminal_input() else {
        bail!(
            "Refusing to directly update {target_display} without confirmation. Re-run with --yes to confirm."
        );
    };

    let question = if extras.is_empty() {
        format!("Land {branch_name} directly onto {target_display}?")
    } else {
        format!("Land {branch_name} and everything below it directly onto {target_display}?")
    };
    if inout.confirm(question, ConfirmDefault::Yes)? == Confirm::No {
        bail!("Land cancelled");
    }

    Ok(())
}

/// The open pull-request numbers attached to `branch_name` or any of `lower_segments`. Landing
/// deletes each landed branch's remote copy, which closes the attached reviews on the forge, so
/// all are surfaced.
///
/// Only applied workspace segments can land, so this reads the forge review associations that
/// `head_info` projects onto the workspace segments instead of computing the repository-wide
/// branch listing. Only open reviews are surfaced: a segment's number can also be settled
/// display identity (a landed review), which landing cannot close.
pub(super) fn attached_pr_numbers(
    ctx: &Context,
    branch_name: &str,
    lower_segments: &[String],
) -> anyhow::Result<Vec<(String, usize)>> {

View on GitHub (pinned to 58e5313667)