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

  1. 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
  2. For general hunk parse failures, inspect the offending string in the error message and fix the `start-end[-hash]` format in the source toml
  3. Pre-validate the format before calling `Hunk::from_str` (see exampleFix) so callers get a clearer error
  4. 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

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


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/3ae17b57446efa1e. Report an issue: GitHub.