gitbutlerapp/gitbutler · error
No commits were provided to cherry-pick
Error message
No commits were provided to cherry-pick
What it means
cherry_pick_commits deduplicates the input ids into a Vec and bails when the result is empty. There is nothing to apply, and proceeding would create an empty rebase outcome, so it fails fast. This is a pure caller-input error; no editor state has been consumed.
Source
Thrown at crates/but-workspace/src/commit/cherry_pick.rs:34
/// Sources are read from the object database, so they may live anywhere in the repository,
/// including on branches that aren't part of the workspace. Duplicates are dropped, keeping the
/// first occurrence, and the rest are applied in the order given rather than reordered, like
/// `git cherry-pick`: the first source lands at `side` of `relative_to`, and each later one
/// directly above the one before it.
/// Child commits, and the target commit, if applicable, are rebased atop the cherry-picked commits.
pub fn cherry_pick_commits<'ws, 'meta, M: RefMetadata>(
mut editor: Editor<'ws, 'meta, M>,
source_commits: impl IntoIterator<Item = gix::ObjectId>,
relative_to: RelativeTo,
side: InsertSide,
) -> anyhow::Result<(SuccessfulRebase<'ws, 'meta, M>, Vec<Selector>)> {
let mut seen = HashSet::new();
let sources = source_commits
.into_iter()
.filter(|id| seen.insert(*id))
.collect::<Vec<_>>();
if sources.is_empty() {
bail!("No commits were provided to cherry-pick")
}
if matches!(
(&relative_to, side),
(RelativeTo::Reference(_), InsertSide::Above)
) {
bail!("Cannot cherry-pick above a reference")
}
let target = relative_to.to_selector(&editor)?;
let mut inserted_selectors = Vec::with_capacity(sources.len());
let mut previous_selector = None;
for source in sources {
// Give the copy its own change ID, retaining all other metadata.
let mut template = editor.find_commit(source)?;
let mut headers = Headers::try_from_commit(&template.inner).unwrap_or_default();
headers.change_id = Headers::from_config(&editor.repo().config_snapshot()).change_id;
headers.set_in_commit(&mut template.inner);View on GitHub (pinned to caf1f223d3)
Solutions
- Guard the call: if the selection is empty, skip the operation (no-op) instead of invoking the API.
- Fix the caller that produced an empty commit list (selection state, filter bug).
- In batch processing, filter empty batches before calling.
Example fix
// before
cherry_pick_commits(editor, selected_ids, relative_to, side)?;
// after
if selected_ids.is_empty() {
return Ok((successful_rebase, vec![])); // nothing to pick
}
cherry_pick_commits(editor, selected_ids, relative_to, side)?; Defensive patterns
Strategy: validation
Validate before calling
let ids: Vec<_> = source_commits.into_iter().collect::<HashSet<_>>().into_iter().collect();
if ids.is_empty() {
// nothing selected: no-op instead of an API error
return Ok((successful_rebase, vec![]));
} Prevention
- Require a non-empty selection before enabling cherry-pick actions.
- Guard batch callers: skip empty chunks instead of invoking the API.
- Unit-test boundary: empty iterator and single-id iterator.
When it happens
Trigger: Calling cherry_pick_commits with an empty iterator, or with an iterator whose items all deduplicate away (single id repeated is still one entry — only zero unique ids triggers this).
Common situations: UI 'cherry-pick selected commits' invoked with an empty selection; upstream list filtered down to nothing before the call; batch loops where one chunk is legitimately empty.
Related errors
- Invalid message format
- HTTP Error ${response.statusText}: ${text}
- Cannot move branch {subject_branch_name} onto itself
- Cannot cherry-pick above a reference
- Failed to communicate with LM Studio server: ${error instanc
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/fecf0583bfb2f392.
Report an issue: GitHub.