{"record":{"id":"47f39e8c8dc021e6","repo":"gitbutlerapp/gitbutler","slug":"invalid-range-start-end","errorCode":null,"errorMessage":"invalid range: {start}-{end}","messagePattern":"invalid range: (.+?)-(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-meta/src/virtual_branches_legacy_types.rs","lineNumber":422,"sourceCode":"                if raw_hash.is_empty() {\n                    None\n                } else {\n                    let mut buf = [0u8; 16];\n                    hex::decode_to_slice(raw_hash, &mut buf)?;\n                    Some(md5::Digest(buf))\n                }\n            } else {\n                None\n            };\n\n            Hunk::new(start, end, hash)\n        }\n    }\n\n    impl Hunk {\n        pub fn new(start: u32, end: u32, hash: Option<HunkHash>) -> anyhow::Result<Self> {\n            if start > end {\n                Err(anyhow!(\"invalid range: {start}-{end}\"))\n            } else {\n                Ok(Hunk {\n                    hash,\n                    start,\n                    end,\n                    hunk_header: None,\n                })\n            }\n        }\n    }\n\n    #[derive(Debug, PartialEq, Clone)]\n    pub struct HunkHeader {\n        pub old_start: u32,\n        pub old_lines: u32,\n        pub new_start: u32,\n        pub new_lines: u32,\n    }","sourceCodeStart":404,"sourceCodeEnd":440,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-meta/src/virtual_branches_legacy_types.rs#L404-L440","documentation":"Thrown by `Hunk::new(start, end, hash)` when `start > end`, i.e. the range is inverted. `Hunk::from_str` funnels parsed values through this constructor, so both direct construction and string parsing of an inverted range like \"58-12\" produce it. The message echoes the offending pair as `{start}-{end}`.","triggerScenarios":"`Hunk::new(58, 12, None)`, or `Hunk::from_str(\"58-12\")` — any input where the first number exceeds the second; also arithmetic that computes an end before swapping or diff-hunk merging bugs producing inverted ranges.","commonSituations":"Corrupted legacy toml with reversed hunk bounds; code that computes (new_start, old_end) from diff edits and gets the ordering wrong; fixture data generated by scripts that don't enforce ordering.","solutions":["Fix the data or computation so start <= end","If the inversion is a known artifact, normalize by swapping bounds before calling `Hunk::new` (only if semantically valid for your data)","Add a debug assertion or test in the producer of hunk ranges so inversions are caught where they are created, not at parse time"],"exampleFix":"// before\nlet hunk = Hunk::new(58, 12, None)?; // Err: invalid range: 58-12\n\n// after\nlet hunk = Hunk::new(12, 58, None)?;","handlingStrategy":"validation","validationCode":"let (start, end) = if start <= end { (start, end) } else { anyhow::bail!(\"hunk bounds inverted: {start} > {end}\") };\nlet hunk = Hunk::new(start, end, hash)?;","typeGuard":"fn is_valid_range(start: u32, end: u32) -> bool {\n    start <= end\n}","tryCatchPattern":null,"preventionTips":["Assert start <= end where ranges are computed (diff hunk merging, edit scripts)","Prefer constructing hunks from parsed `start-end` strings so bounds keep source ordering"],"tags":["rust","validation","range","legacy-format","virtual-branches"],"backgroundTag":"range-validation-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}