gitbutlerapp/gitbutler · error
Invalid selector set: This cannot be empty
Error message
Invalid selector set: This cannot be empty
What it means
`SomeSelectors::new` builds a `SelectorSet::Some` for graph-rebase editor operations and refuses an empty selector list — an empty `Some` set is meaningless because 'select some' with nothing selected is either a no-op or a typo for `SelectorSet::All`/`None`. The error is a guard against caller mistakes before any graph mutation begins.
Source
Thrown at crates/but-rebase/src/graph_rebase/mutate.rs:73
/// A set of some selectors
#[derive(Debug, Clone)]
pub struct SomeSelectors {
selectors: Vec<AnySelector>,
}
impl SomeSelectors {
/// Creates a set of selectors from different selector input types.
///
/// Errors out if the selectors iterator is empty.
pub fn new<T>(selectors: impl IntoIterator<Item = T>) -> Result<Self>
where
T: Into<AnySelector>,
{
let selectors: Vec<AnySelector> = selectors.into_iter().map(Into::into).collect();
if selectors.is_empty() {
return Err(anyhow!("Invalid selector set: This cannot be empty"));
}
Ok(Self { selectors })
}
/// Returns selectors as a slice.
pub fn as_slice(&self) -> &[AnySelector] {
&self.selectors
}
}
/// A heterogeneous selector input.
#[derive(Debug, Clone)]
pub enum AnySelector {
/// A selector that already points into the current graph revision.
Selector(Selector),
/// A commit id that should resolve to a pick step.
Commit(gix::ObjectId),View on GitHub (pinned to caf1f223d3)
Solutions
- Check the selector list is non-empty before constructing `SomeSelectors`
- Decide the intended semantics for 'nothing matched': use `SelectorSet::All` (everything), `SelectorSet::None` (nothing), or early-return from the operation
- Trace where the empty list came from — usually an upstream filter or user selection that legitimately produced zero items
Example fix
// before
let selectors = SomeSelectors::new(matching_commits)?; // panics path: Err when empty
// after
let set = if matching_commits.is_empty() {
SelectorSet::All // or early-return, per intended semantics
} else {
SelectorSet::Some(SomeSelectors::new(matching_commits)?)
}; Defensive patterns
Strategy: validation
Validate before calling
let selector_set = if selectors.is_empty() {
anyhow::bail!("no selectors matched; refusing SelectorSet::Some(empty)");
} else {
SelectorSet::Some(SomeSelectors::new(selectors)?)
}; Prevention
- Never construct SomeSelectors from a filter result without checking emptiness
- Decide All/None semantics at the call site before building the set
- Add a helper `SelectorSet::from_optional(list)` so the empty case is handled in one place
When it happens
Trigger: Passing an empty Vec to `SomeSelectors::new(...)`, e.g. building `parents_to_disconnect` from a filter that matched nothing, then calling `Editor::disconnect_segment_from` with `SelectorSet::Some(empty)`.
Common situations: Calling code that computes selectors dynamically (commits matching a predicate, branches from user selection) and hits an empty result; UI actions invoked with nothing selected.
Related errors
- Invalid parents to disconnect: SelectorSet::None is not allo
- Invalid parent delimitation: requested parent is not a direc
- Invalid parent delimitation: requested child is not a direct
- No rebase steps provided
- Invalid message format
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/9393f18c017738b0.
Report an issue: GitHub.