{"record":{"id":"c499aedfc3292fc1","repo":"gitbutlerapp/gitbutler","slug":"selection-aborted","errorCode":null,"errorMessage":"Selection aborted","messagePattern":"Selection aborted","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/but/src/command/legacy/push.rs","lineNumber":930,"sourceCode":"            (label, candidate.branch_name.clone())\n        })\n        .collect::<Vec<_>>();\n    let options = nonempty::NonEmpty::from_vec(options).context(\"No branches available to push\")?;\n    let mut input = out\n        .prepare_for_terminal_input()\n        .context(\"Human input required - run this in a terminal\")?;\n\n    // Preselect everything so plain Enter pushes all candidates; the picker\n    // starts empty otherwise, making Enter a silent no-op.\n    let selected_branches = input\n        .prompt_multi_select_with_help(\n            \"Which branch(es) would you like to push?\",\n            &options,\n            (0..options.len()).collect(),\n            Vec::new(),\n            |_| None,\n        )?\n        .ok_or_else(|| anyhow::anyhow!(\"Selection aborted\"))?\n        .into_iter()\n        .cloned()\n        .collect::<Vec<_>>();\n\n    if selected_branches.is_empty() {\n        Ok(BranchSelection::None)\n    } else {\n        Ok(BranchSelection::Selected(selected_branches))\n    }\n}\n\n/// A branch worth offering for push: the topmost branch with unpushed commits\n/// in its stack. Pushing a branch always pushes its stack ancestors too, so\n/// lower branches of the same stack are folded into one candidate instead of\n/// being offered (and pushed) separately.\nstruct PushCandidate {\n    branch_name: String,\n    /// Unpushed commits across this branch and its ancestors.","sourceCodeStart":912,"sourceCodeEnd":948,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/push.rs#L912-L948","documentation":"`but push` with several unpushed candidates opens `prompt_multi_select_with_help(\"Which branch(es) would you like to push?\", ...)` with every option preselected, so plain Enter pushes all candidates. A `None` return — a cancelled prompt — becomes this error; a confirmed-but-empty selection is separately mapped to `BranchSelection::None`.","triggerScenarios":"Running `but push` interactively with multiple branches that have unpushed commits and cancelling the picker with Esc/Ctrl-C.","commonSituations":"User opens the picker to inspect candidates and aborts; terminal multiplexer sends an unexpected key; automation surprised by an inherited TTY.","solutions":["Press Enter to accept the preselected full list","Space-toggle individual branches, then Enter","Name the branch to skip the picker entirely: `but push <branch>`","If aborted on purpose, note that nothing was pushed — no state changed"],"exampleFix":"# before\nbut push\n# (cancel the 'Which branch(es) would you like to push?' picker)\n# error: Selection aborted\n\n# after\nbut push              # Enter pushes all preselected candidates\nbut push my-branch    # or skip the picker by naming the branch","handlingStrategy":"fallback","validationCode":"# Script-safe: name branches so no picker appears\nbut push my-branch","typeGuard":null,"tryCatchPattern":"# Map cancellation to a clean exit in wrappers\nout=$(but push 2>&1); rc=$?\nif [ $rc -ne 0 ] && [[ \"$out\" == *\"Selection aborted\"* ]]; then exit 0; fi\necho \"$out\"; exit $rc","preventionTips":["In scripts always pass the branch argument to `but push`","Remember Enter accepts the full preselected list","Cancelling leaves the repo untouched — safe to simply retry"],"tags":["interactive","prompt","push","selection"],"backgroundTag":"interactive-prompt-cancelled","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}