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
- Re-run the command and answer 'Yes' (the default) at the confirmation prompt if the landing is intended.
- Add the `--yes` flag to skip interactive confirmation: `but merge <branch-id> --yes` (only when certain of the target).
- Use `--whole-stack` only intentionally; if the prompt showed unwanted extras, land a single branch instead by omitting `--whole-stack`.
- 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
- Pass --yes when the landing is intentional and the command runs non-interactively.
- Read the warning above the prompt (attached PRs, extras below) before answering.
- Use --whole-stack deliberately only when all lower branches should land too.
- Verify target remote/branch display (push_remote/target) before confirming.
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
- Land cancelled
- Ambiguous branch ' ', matches multiple items
- Ambiguous branch ' ', matches multiple items
- `but land` requires an active GitButler workspace…
- `but merge` requires an active GitButler workspace…
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)