nautechsystems/nautilus_trader · error
Failed to subtract {n} years from {datetime}
Error message
Failed to subtract {n} years from {datetime} What it means
subtract_n_years delegates to shift_months with a negative month delta; if the resulting date would be invalid or precedes the representable Timestamp minimum (before the UNIX epoch / i64 nanosecond floor), shift_months fails and this contextual error is returned. It signals the requested subtraction is not representable.
Source
Thrown at crates/core/src/datetime.rs:626
anyhow::anyhow!("Failed to add {n} years to {datetime}: month count overflow")
})?;
shift_months(datetime, i64::from(months))
.map_err(|_| anyhow::anyhow!("Failed to add {n} years to {datetime}"))
}
/// Subtract `n` years from a Jiff [`Timestamp`].
///
/// # Errors
///
/// Returns an error if the resulting date would be invalid or out of range.
pub fn subtract_n_years(datetime: Timestamp, n: u32) -> anyhow::Result<Timestamp> {
let months = n.checked_mul(12).ok_or_else(|| {
anyhow::anyhow!("Failed to subtract {n} years from {datetime}: month count overflow")
})?;
shift_months(datetime, -i64::from(months))
.map_err(|_| anyhow::anyhow!("Failed to subtract {n} years from {datetime}"))
}
/// Add `n` years to a given UNIX nanoseconds timestamp.
///
/// # Errors
///
/// Returns an error if the resulting timestamp is out of range or invalid.
pub fn add_n_years_nanos(unix_nanos: UnixNanos, n: u32) -> anyhow::Result<UnixNanos> {
let datetime = unix_nanos.to_datetime_utc();
let result = add_n_years(datetime, n)?;
let timestamp = result.as_nanosecond();
let nanos =
u64::try_from(timestamp).map_err(|_| anyhow::anyhow!("Negative timestamp not allowed"))?;
Ok(UnixNanos::from(nanos))
}
/// Subtract `n` years from a given UNIX nanoseconds timestamp.View on GitHub (pinned to 18893faf8b)
Solutions
- Check the resulting date stays above the timestamp minimum before subtracting; clamp the lookback.
- Reduce the year offset to keep the result representable.
- Propagate the Result instead of unwrapping, and log the offending datetime/n.
Example fix
// before
let start = subtract_n_years(end, lookback_years)?;
// after
let lookback_years = lookback_years.min(50);
let start = match subtract_n_years(end, lookback_years) {
Ok(ts) => ts,
Err(_) => end, // clamp to epoch-ish floor
}; Defensive patterns
Strategy: try-catch
Validate before calling
// ensure result stays above timestamp minimum
if datetime < jiff::Timestamp::MIN + jiff::Span::new().years(n as i32) { /* clamp */ } Try / catch
let start = subtract_n_years(end, lookback).unwrap_or_else(|_| jiff::Timestamp::MIN);
Prevention
- Clamp lookbacks near the epoch to a safe floor.
- Verify timestamps are in nanoseconds before multi-year arithmetic.
When it happens
Trigger: subtract_n_years(datetime, n) where datetime - n*12 months falls outside the valid Timestamp range (e.g. subtracting many years from a timestamp near the epoch), or yields an invalid calendar date.
Common situations: Backfill/lookback code subtracting large lookback periods from timestamps already near the epoch; tests exercising pre-epoch subtraction; bad config giving an oversized lookback.
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
- DateTime timestamp out of range for UnixNanos: {nanos}
- seconds {secs} is out of range for `u64` nanoseconds
- seconds {secs} is out of range for `u64` milliseconds
- milliseconds {millis} is out of range for `u64` nanoseconds
- microseconds {micros} is out of range for `u64` nanoseconds
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4ab1932a68a2356a.
Report an issue: GitHub.