gitbutlerapp/gitbutler · error
no searchable columns
Error message
no searchable columns
What it means
The TUI fuzzy picker enforces a trait contract: FuzzyPickerItem::columns(SearchableToken(())) must return at least one Col with searchable == Some. During layout the picker inspects only the first item (self.items[0]) to locate the searchable column index and panics if none of its columns is searchable. Because it also indexes items[0], an empty items list panics with index-out-of-bounds just before this expect.
Source
Thrown at crates/but/src/command/legacy/status/tui/fuzzy_picker.rs:118
let input_height: u16 = 1;
let col_widths = self
.items
.iter()
.map(|item| item.columns(SearchableToken(())))
.map(|cols| {
cols.into_iter()
.map(|col| col.text.width())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
// assume the searchable column is at the same index on every row
let searchable_col_idx = self.items[0]
.columns(SearchableToken(()))
.into_iter()
.position(|col| col.searchable.is_some())
.expect("no searchable columns");
// assume each row contains the same number of columns
let num_cols = col_widths[0].len();
let column_spacing = 2;
let mut col_constraints = (0..num_cols)
.map(|n| col_widths.iter().map(|c| &c[n]).collect::<Vec<_>>())
.map(|col| col.iter().copied().max().unwrap())
.map(|&width| Constraint::Length(width as u16))
.collect::<Vec<_>>();
for (i, constraint) in col_constraints.iter_mut().enumerate() {
if i == searchable_col_idx {
*constraint = Constraint::Min(1);
break;
}
}
View on GitHub (pinned to 2497b8007a)
Solutions
- In the FuzzyPickerItem::columns impl, set searchable: Some(searchable) on exactly one Col (copy the pattern from fuzzy_picker.rs sibling copy_selection_picker.rs:236-240)
- Guard the caller: don't open the picker when items.is_empty() — show a 'nothing to pick' message instead
- Replace the expect with a fallback (search column 0) or skip rendering, so contract violations surface as wrong UI instead of a crash
- Add a unit test that builds the picker for each item type and asserts a searchable column exists
Example fix
// before — new item impl, nothing searchable → panic at layout
fn columns(&self, _searchable: SearchableToken) -> impl IntoIterator<Item = Col<'_>> {
[Col { text: self.name.clone(), searchable: None }]
}
// after — mark the column users fuzzy-search on
fn columns(&self, searchable: SearchableToken) -> impl IntoIterator<Item = Col<'_>> {
[Col { text: self.name.clone(), searchable: Some(searchable) }]
} Defensive patterns
Strategy: validation
Validate before calling
// before constructing/opening the picker
fn picker_items_valid(items: &[impl FuzzyPickerItem]) -> bool {
!items.is_empty()
&& items.iter().all(|i| i.columns(SearchableToken(())).into_iter().any(|c| c.searchable.is_some()))
}
if !picker_items_valid(&items) { /* show 'nothing to pick' instead of opening the picker */ } Type guard
fn has_searchable_column(item: &impl FuzzyPickerItem) -> bool {
item.columns(SearchableToken(()))
.into_iter()
.any(|col| col.searchable.is_some())
} Prevention
- Always attach the SearchableToken parameter to exactly one column in every FuzzyPickerItem impl
- Copy a known-good impl (copy_selection_picker.rs:236) when adding item types
- Never pass an empty items vec to the picker; short-circuit with an empty-state message
- Add a per-item-type unit test asserting a searchable column exists
When it happens
Trigger: Opening any fuzzy picker in the TUI (copy-selection picker, stack picker) where the item type's columns impl returns every Col with searchable: None, or drops the SearchableToken parameter instead of attaching it to exactly one column; also constructing a picker with an empty items vec (empty workspace/stack).
Common situations: Implementing FuzzyPickerItem for a new TUI list type and forgetting to mark the searchable column (reference impls: copy_selection_picker.rs:236, app/mod.rs:2066 set searchable: Some on the searched column); conditional impls that only sometimes mark a column searchable; empty result lists passed to the picker.
Related errors
- FuzzyPickerItem::columns must return a searchable column
- line should have been highlighted by now
- symbols must always be initialized
- Failed to persist action: {e}
- Failed to list actions: {e}
AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17).
Data as JSON: /api/errors/15e71be450e6bb37.
Report an issue: GitHub.