gitbutlerapp/gitbutler · error
invalid range: {s}
Error message
invalid range: {s} What it means
Thrown by `Hunk::from_str` (legacy virtual-branches.toml hunk parser) when `s.split('-')` yields no first component while parsing the hunk range start. In practice this arm is unreachable: Rust's `split` always returns at least one item, so a malformed string like "" or "abc" instead fails with the "failed to parse start of range: ..." context error. Seeing this exact message means the defensive else-branch fired, which should be treated as a parser bug rather than bad input. The expected hunk string format is `start-end` optionally followed by a third `-<md5-hex>` segment.
Source
Thrown at crates/but-meta/src/virtual_branches_legacy_types.rs:392
/// The index of the first line this hunk is representing.
pub start: u32,
/// The index of *one past* the last line this hunk is representing.
pub end: u32,
/// Only set by the frontend when amending
pub hunk_header: Option<HunkHeader>,
}
impl FromStr for Hunk {
type Err = anyhow::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let mut range = s.split('-');
let start = if let Some(raw_start) = range.next() {
raw_start
.parse::<u32>()
.context(format!("failed to parse start of range: {s}"))
} else {
Err(anyhow!("invalid range: {s}"))
}?;
let end = if let Some(raw_end) = range.next() {
raw_end
.parse::<u32>()
.context(format!("failed to parse end of range: {s}"))
} else {
Err(anyhow!("invalid range: {s}"))
}?;
let hash = if let Some(raw_hash) = range.next() {
if raw_hash.is_empty() {
None
} else {
let mut buf = [0u8; 16];
hex::decode_to_slice(raw_hash, &mut buf)?;
Some(md5::Digest(buf))
}View on GitHub (pinned to caf1f223d3)
Solutions
- If this exact message appears, report it as a bug in the `Hunk` FromStr implementation (dead defensive branch), since split('-') cannot return an empty iterator
- For general hunk parse failures, inspect the offending string in the error message and fix the `start-end[-hash]` format in the source toml
- Pre-validate the format before calling `Hunk::from_str` (see exampleFix) so callers get a clearer error
- If parsing legacy data wholesale, isolate the failing line and skip/log it instead of aborting the whole workspace load
Example fix
// before
let hunk = Hunk::from_str(input)?; // opaque 'invalid range' / parse errors
// after
anyhow::ensure!(
input.split('-').count() >= 2,
"hunk must be 'start-end[-hash]': {input}"
);
let hunk = Hunk::from_str(input)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_hunk_str(s: &str) -> bool {
let mut parts = s.split('-');
let (Some(a), Some(b), rest_is_ok) = (parts.next(), parts.next(), true) else {
return false;
};
a.parse::<u32>().is_ok() && b.parse::<u32>().is_ok() && rest_is_ok
} Try / catch
match Hunk::from_str(s) {
Ok(h) => { /* ... */ }
Err(e) if s.split('-').count() < 2 => log::warn!("malformed hunk line (expected start-end): {s} ({e:#})"),
Err(e) => return Err(e),
} Prevention
- Emit hunk lines as `start-end[-hash]` from any tool that writes legacy virtual-branches data
- Validate format at load boundaries and quarantine bad lines instead of aborting the workspace
- Add round-trip tests (serialize -> parse) for hunk data
When it happens
Trigger: Theoretically only if `s.split('-').next()` returned None, which the stdlib never does. Real-world hunk parse failures on strings like "", "abc", or "5" surface as the sibling parse-context errors or error 641 instead.
Common situations: Hand-edited or corrupted legacy `virtual_branches.toml` files; migration tooling that writes hunk lines in an unexpected format; test fixtures with malformed hunk strings.
Related errors
- invalid range: {start}-{end}
- No uncommitted changes assigned to branch: {branch_name}
- Unable to determine target commit for unassigned change: {}
- Cannot unapply anonymous segments yet even if they have a st
- line {line_number}: pick does not accept a message clause
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/3ae17b57446efa1e.
Report an issue: GitHub.