{"record":{"id":"d4b5d154d8491133","repo":"gitbutlerapp/gitbutler","slug":"subtraction-overflow-self-b","errorCode":null,"errorMessage":"Subtraction overflow: {self} - {b}.","messagePattern":"Subtraction overflow: (.+?) - (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-hunk-dependency/src/utils.rs","lineNumber":9,"sourceCode":"pub(crate) trait PaniclessSubtraction<T> {\n    /// Subtract on T from another or fail if there is an overflow.\n    fn sub_or_err(&self, b: T) -> anyhow::Result<u32>;\n}\n\nimpl PaniclessSubtraction<u32> for u32 {\n    fn sub_or_err(&self, b: u32) -> anyhow::Result<u32> {\n        self.checked_sub(b)\n            .ok_or_else(|| anyhow::anyhow!(\"Subtraction overflow: {self} - {b}.\"))\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":12,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-hunk-dependency/src/utils.rs#L1-L12","documentation":"The PaniclessSubtraction trait wraps u32 subtraction so that an underflow (subtracting a larger u32 from a smaller one, which would panic in debug builds) becomes an anyhow error instead. It is thrown by sub_or_err whenever `checked_sub` returns None.","triggerScenarios":"Calling sub_or_err(b) where self < b on any u32 using this trait, e.g. computing remaining line counts or offsets in hunk-dependency calculations where the subtrahend exceeds the minuend.","commonSituations":"Diff statistics where old_lines exceeds new_lines unexpectedly; off-by-one in range computations; malformed diff input producing inverted ranges.","solutions":["Check the operands before subtracting (if a >= b) or handle the error","Reverse the operand order if the subtraction was accidentally inverted","Use saturating_sub if a clamped 0 result is acceptable for the use case"],"exampleFix":"// before\nlet remaining = a.sub_or_err(b)?;\n// after\nlet remaining = if a >= b { a - b } else { 0 }; // or handle explicitly","handlingStrategy":"validation","validationCode":"fn safe_sub(a: u32, b: u32) -> Option<u32> { a.checked_sub(b) }\n// ensure a >= b before calling sub_or_err","typeGuard":null,"tryCatchPattern":"match a.sub_or_err(b) {\n    Ok(v) => v,\n    Err(e) => { eprintln!(\"{e:#}\"); return Err(e); }\n}","preventionTips":["Assert operand ordering (a >= b) at call sites","Prefer checked_sub/saturating_sub for inline arithmetic","Unit-test diff computations with old_lines > new_lines cases"],"tags":["arithmetic-overflow","rust","underflow"],"backgroundTag":"value-out-of-range","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}