nautechsystems/nautilus_trader · error
DateTime timestamp out of range for UnixNanos: {nanos}
Error message
DateTime timestamp out of range for UnixNanos: {nanos} What it means
`try_datetime_to_unix_nanos` converts a DateTime into the library's `UnixNanos` (u64 nanoseconds since epoch). It rejects negative timestamps outright, and errors with this message when the nanosecond value is positive but exceeds what a u64 can represent (or otherwise cannot be converted from i64). The library throws it to prevent silently wrapping/overflowing the internal u64 timestamp representation.
Source
Thrown at crates/core/src/datetime.rs:681
.and_then(|nanos| u64::try_from(nanos).ok())
.map(UnixNanos::from)
}
/// Converts a `Timestamp` to `UnixNanos`.
///
/// Unlike `UnixNanos::from(Timestamp)` which panics, this returns an error.
///
/// # Errors
///
/// Returns an error if the timestamp is before the UNIX epoch or out of range for `UnixNanos`.
pub fn try_datetime_to_unix_nanos(value: Timestamp) -> anyhow::Result<UnixNanos> {
let nanos = value.as_nanosecond();
if nanos < 0 {
anyhow::bail!("DateTime timestamp cannot be negative: {nanos}");
}
let nanos = u64::try_from(nanos)
.map_err(|_| anyhow::anyhow!("DateTime timestamp out of range for UnixNanos: {nanos}"))?;
Ok(UnixNanos::from(nanos))
}
#[cfg(test)]
// `allow` not `expect`: nightly clippy does not fire `float_cmp` inside `assert_eq!`
#[allow(
clippy::float_cmp,
reason = "Exact float comparisons acceptable in tests"
)]
mod tests {
use jiff::SignedDuration;
use proptest::prelude::*;
use rstest::rstest;
use super::*;
fn timestamp(value: &str) -> Timestamp {View on GitHub (pinned to 18893faf8b)
Solutions
- Clamp or validate the DateTime to a sane range (e.g. before year 2554 / u64::MAX ns) before converting
- Check unit conversions: ensure you are not multiplying milliseconds or seconds by an extra 1e9 factor
- Use a smaller sentinel value (e.g. a few years in the future) for 'max' expiry semantics
- If you need beyond-u64-nanosecond ranges, handle the error and switch to a different representation
Example fix
// before let nanos = try_datetime_to_unix_nanos(far_future_dt)?; // after let max_dt = DateTime::from_timestamp(9223372036, 0).unwrap(); // well within u64 ns let nanos = try_datetime_to_unix_nanos(dt.min(max_dt))?;
Defensive patterns
Strategy: validation
Validate before calling
let nanos = value.as_nanosecond();
if nanos < 0 || nanos > i64::from(u64::MAX) {
// clamp or reject before calling try_datetime_to_unix_nanos
}
let unix_nanos = try_datetime_to_unix_nanos(value)?; Type guard
fn is_representable_as_unix_nanos(value: &DateTime) -> bool {
let nanos = value.as_nanosecond();
nanos >= 0 && u64::try_from(nanos).is_ok()
} Try / catch
match try_datetime_to_unix_nanos(dt) {
Ok(nanos) => use(nanos),
Err(e) => tracing::error!("timestamp out of range: {e}"), // clamp/fallback
} Prevention
- Validate datetime ranges at config-parse time, not deep in the call chain
- Beware unit conversions that inflate ms/s values into nanoseconds
- Use bounded sentinel values for 'never expires' semantics
When it happens
Trigger: Calling `try_datetime_to_unix_nanos` with a DateTime whose `as_nanosecond()` value is greater than u64::MAX nanoseconds (roughly year 2554). Negative timestamps get a different message, so this one specifically fires on far-future dates.
Common situations: Constructing expiry or alert times with an overly large year (e.g. misparsing a year like '99999' or unit confusion, milliseconds treated as nanoseconds multiplied incorrectly); using a far-future sentinel 'never expires' timestamp; passing a datetime built from unvalidated user input.
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
- 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
- Negative timestamp: {unix_timestamp_ns}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9e808c160569f2c6.
Report an issue: GitHub.