GitoxideLabs/gitoxide · error
Failed to subtract from
Error message
Failed to subtract {duration} from {now} What it means
gix-date's relative-date parser (`subtract_duration`, used by `parse_named`) computes an absolute timestamp by subtracting a parsed duration (e.g. from "2 hours ago") from the current time via `checked_sub`. This error is raised when that arithmetic overflows — the duration is too large to subtract from the given `now` timestamp — and wraps the failure with context showing the duration and the base time.
Solutions
- Validate the magnitude of the relative duration before parsing (reject absurdly large numbers).
- Provide a sane `now` reference (`Some(&Zoned::now())`) so subtraction happens in a normal range.
- Catch the error and surface 'invalid relative date' to the user instead of propagating.
Example fix
// before: extreme spec overflows when subtracted from now
let t = gix_date::parse::named("99999999999 years ago", Some(&now))?;
// after: bound the numeric part before parsing
let n: u64 = spec.trim_end_matches(...).parse()?;
if n > 1_000_000 { return Err(anyhow::anyhow!("relative date too large")); }
let t = gix_date::parse::named(spec, Some(&now))?; Defensive patterns
Strategy: try-catch
Validate before calling
let n: u64 = /* numeric part of spec */;
if n > 1_000_000 { return Err(anyhow::anyhow!("relative date magnitude too large")); } Try / catch
match gix_date::parse::named(spec, Some(&now)) {
Ok(t) => t,
Err(_) => anyhow::bail!("invalid relative date: {spec}"),
} Prevention
- Always pass an explicit `now` reference instead of None.
- Bound user-supplied numeric durations before parsing.
- Map parse failures to a user-facing 'invalid date' message in CLI input handling.
When it happens
Trigger: Calling `gix_date::parse::named` (or the relative parser it delegates to) with a relative date spec whose duration exceeds the representable timestamp range when subtracted from `now`, e.g. an enormous number of years/durations near the timestamp limits.
Common situations: User-supplied free-form date input like "999999999999 years ago" accepted by a CLI or config; fuzzed or malicious input to a date parser; unit tests passing extreme durations.
Related errors
- Day lies out of range
- Couldn't parse span from
- cannot find character that we didn't search for
- Date lies out of range
- LEB64 value overflowed
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/9ffd4cfedcedac62.
Report an issue: GitHub.
Appendix: source
Thrown at gix-date/src/parse/relative.rs:213
let months = count.checked_mul(*factor).ok_or_else(err)?;
fields = fields.normalize()?.into();
let total = (i64::from(fields.year) * 12 + i64::from(fields.month) - 1)
.checked_sub(months)
.ok_or_else(err)?;
fields.year = i16::try_from(total.div_euclid(12)).ok().ok_or_else(err)?;
fields.month = i8::try_from(total.rem_euclid(12) + 1).expect("a value in 1..=12");
}
}
}
fields.normalize()
}
fn subtract_duration(now: Option<&Zoned>, duration: SignedDuration) -> Result<Zoned, Exn<ValidationError>> {
let now = now.ok_or(ValidationError::new("Missing current time"))?;
now.timestamp()
.checked_sub(duration)
.map(|timestamp| timestamp.to_zoned(now.time_zone().clone()))
.or_raise(|| Error::new(format!("Failed to subtract {duration} from {now}")))
}
View on GitHub (pinned to e73179060b)