nautechsystems/nautilus_trader · error
Negative timestamp: {unix_timestamp_ns}
Error message
Negative timestamp: {unix_timestamp_ns} What it means
After computing midnight-UTC of the adjusted weekday, last_weekday_nanos converts the signed nanosecond timestamp to u64 for UnixNanos; a negative value means the date falls before the UNIX epoch (1970-01-01), which UnixNanos cannot represent. The library throws it because UnixNanos is an unsigned u64 nanosecond count.
Source
Thrown at crates/core/src/datetime.rs:521
// Calculate the offset in days for closest weekday (Mon-Fri)
let offset = match current_weekday {
1..=5 => 0, // Monday to Friday, no adjustment needed
6 => 1, // Saturday, adjust to previous Friday
_ => 2, // Sunday, adjust to previous Friday
};
// Calculate last closest weekday
let last_closest = date.checked_sub(Span::new().days(offset))?;
// Convert to UNIX nanoseconds
let unix_timestamp_ns = last_closest
.at(0, 0, 0, 0)
.to_zoned(TimeZone::UTC)?
.timestamp()
.as_nanosecond();
let ns_u64 = u64::try_from(unix_timestamp_ns)
.map_err(|_| anyhow::anyhow!("Negative timestamp: {unix_timestamp_ns}"))?;
Ok(UnixNanos::from(ns_u64))
}
/// Check whether the given UNIX nanoseconds timestamp is within the last 24 hours.
///
/// # Errors
///
/// Returns an error if the timestamp is invalid.
pub fn is_within_last_24_hours(timestamp_ns: UnixNanos) -> anyhow::Result<bool> {
// Use the time seam so the comparison is deterministic under
// `simulation` + `cfg(madsim)` and we avoid a wall-clock call that
// would otherwise bypass the DST contract.
let timestamp_ns = timestamp_ns.as_u64();
let now_ns = nanos_since_unix_epoch();
// Future timestamps are not within the last 24 hours
if timestamp_ns > now_ns {
return Ok(false);View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure input dates are on or after 1970-01-01; clamp or reject earlier dates at the call site.
- If pre-epoch timestamps are genuinely needed, use a signed timestamp type (jiff Timestamp / i64 nanos) instead of UnixNanos.
- Check for accidental negative years caused by sign or argument-order mistakes.
Example fix
// before let ns = last_weekday_nanos(1969, 7, 20)?; // pre-epoch -> negative timestamp // after debug_assert!(year >= 1970); let ns = last_weekday_nanos(1970, 1, 2)?;
Defensive patterns
Strategy: validation
Validate before calling
// Rust: reject pre-epoch dates before calling
if year < 1970 { return Err(anyhow!("date {year} is before UNIX epoch")); } Try / catch
let ns = last_weekday_nanos(year, month, day)
.with_context(|| format!("week day anchor for {year}-{month:02}-{day:02}"))?; Prevention
- Remember UnixNanos is unsigned: everything must be >= 1970-01-01T00:00:00Z.
- Check year sign when dates come from subtraction or negation.
When it happens
Trigger: Calling last_weekday_nanos with any date before 1970-01-01, e.g. birthdates, historical data anchors like (1969, 12, 31), or years far in the past such as (1900, 1, 15).
Common situations: Using the function for historical calendar computations rather than market timestamps; a year sign error (-2024 instead of 2024); migrating legacy datasets with pre-epoch dates into nautilus types.
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/379af1118bd7c1bd.
Report an issue: GitHub.