gitbutlerapp/gitbutler · error

Subtraction overflow

Error message

Subtraction overflow: {self} - {b}.

What it means

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.

Solutions

  1. Check the operands before subtracting (if a >= b) or handle the error
  2. Reverse the operand order if the subtraction was accidentally inverted
  3. Use saturating_sub if a clamped 0 result is acceptable for the use case

Example fix

// before
let remaining = a.sub_or_err(b)?;
// after
let remaining = if a >= b { a - b } else { 0 }; // or handle explicitly
Defensive patterns

Strategy: validation

Validate before calling

fn safe_sub(a: u32, b: u32) -> Option<u32> { a.checked_sub(b) }
// ensure a >= b before calling sub_or_err

Try / catch

match a.sub_or_err(b) {
    Ok(v) => v,
    Err(e) => { eprintln!("{e:#}"); return Err(e); }
}

Prevention

When it happens

Trigger: 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.

Common situations: Diff statistics where old_lines exceeds new_lines unexpectedly; off-by-one in range computations; malformed diff input producing inverted ranges.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/d4b5d154d8491133. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-hunk-dependency/src/utils.rs:9

pub(crate) trait PaniclessSubtraction<T> {
    /// Subtract on T from another or fail if there is an overflow.
    fn sub_or_err(&self, b: T) -> anyhow::Result<u32>;
}

impl PaniclessSubtraction<u32> for u32 {
    fn sub_or_err(&self, b: u32) -> anyhow::Result<u32> {
        self.checked_sub(b)
            .ok_or_else(|| anyhow::anyhow!("Subtraction overflow: {self} - {b}."))
    }
}

View on GitHub (pinned to 58e5313667)