gitbutlerapp/gitbutler · error · anyhow::Error
Could not find range from '{}' to '{}' in the displayed file
Error message
Could not find range from '{}' to '{}' in the displayed file list What it means
The but ID parser accepts range selections like '<start>..<end>' over the file IDs currently displayed. After parsing, both endpoint IDs are looked up in get_all_files_in_display_order; if either endpoint is not in that list, the range cannot be resolved and this error is thrown.
Source
Thrown at crates/but/src/id/parser.rs:173
// Both sides must resolve to exactly one Uncommitted entity
if start_matches.len() != 1 || end_matches.len() != 1 {
return Ok(None);
}
if !matches!(&start_matches[0], CliId::UncommittedHunkOrFile(_))
|| !matches!(&end_matches[0], CliId::UncommittedHunkOrFile(_))
{
return Ok(None);
}
// Valid range — resolve positions in display order
let all_files = get_all_files_in_display_order(id_map)?;
let start_pos = all_files.iter().position(|id| id == &start_matches[0]);
let end_pos = all_files.iter().position(|id| id == &end_matches[0]);
match (start_pos, end_pos) {
(Some(s), Some(e)) if s <= e => Ok(Some(all_files[s..=e].to_vec())),
(Some(s), Some(e)) => Ok(Some(all_files[e..=s].to_vec())),
_ => Err(anyhow::anyhow!(
"Could not find range from '{}' to '{}' in the displayed file list",
parts[0],
parts[1]
)),
}
}
fn get_all_files_in_display_order(id_map: &IdMap) -> anyhow::Result<Vec<CliId>> {
let mut files: Vec<(&BStr, CliId)> = id_map
.uncommitted_files
.values()
.map(|uncommitted_file| (uncommitted_file.path(), uncommitted_file.to_id()))
.collect();
files.sort_by_key(|(a_path, _)| *a_path);
Ok(files.into_iter().map(|(_, cli_id)| cli_id).collect())
}
View on GitHub (pinned to caf1f223d3)
Solutions
- Re-run the listing (e.g. `but status`) to refresh the displayed IDs and redo the selection
- Verify both endpoints appear in the current list before using a range
- Use individual IDs instead of a range when the list is volatile
Defensive patterns
Strategy: validation
Validate before calling
let ids = get_all_files_in_display_order(&id_map)?; let endpoints_ok = [start_id, end_id].iter().all(|id| ids.iter().any(|i| i == id)); anyhow::ensure!(endpoints_ok, "range endpoints not in the current file list; re-render");
Try / catch
Treat this error as 'stale selection': re-fetch the current ID list, re-map the user's selection onto fresh IDs, and retry once instead of surfacing the raw error.
Prevention
- Never cache displayed IDs across renders
- Re-render the list immediately before applying a range selection
When it happens
Trigger: Issuing a command with a range argument (e.g. file1..file2) where one endpoint ID does not exist in the current display: a stale ID from an earlier render, a typo, or the file list changed between listing and command.
Common situations: Copy-pasting IDs from an outdated `but status` output; scripts that cache IDs across runs; files staged/hidden between render and command.
Related errors
- Failed to parse diff header
- BUG: It should not be possible to omit sources
- implement list and call recursively
- Refusing to install symlink onto existing non-symlink at '{U
- Run `CARGO_TARGET_DIR=$PWD/target/tauri cargo build -p but`
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/428879ee3fe4cb1e.
Report an issue: GitHub.