nautechsystems/nautilus_trader · error

seconds timestamp should be within valid range

Error message

seconds timestamp should be within valid range

What it means

This panic comes from `Timestamp::from_second(...).expect("seconds timestamp should be within valid range")` in `write_fixed_prefix` in crates/common/src/generators/position_id.rs. The epoch seconds fit into i64 but fall outside the range jiff accepts for a Timestamp (approximately years -9999..9999), so construction fails and the expect panics.

Source

Thrown at crates/common/src/generators/position_id.rs:135

    #[inline]
    fn refresh_fixed_prefix(&mut self, timestamp_ms: u64) {
        let epoch_second = timestamp_ms / 1_000;
        if epoch_second == self.epoch_second {
            return;
        }

        write_fixed_prefix(&mut self.buf, &self.trader_tag, epoch_second);
        self.fixed_prefix_len = self.buf.len();
        self.epoch_second = epoch_second;
    }
}

fn write_fixed_prefix(buf: &mut String, trader_tag: &str, epoch_second: u64) {
    let now_utc = Offset::UTC.to_datetime(
        Timestamp::from_second(
            i64::try_from(epoch_second).expect("seconds timestamp should fit i64"),
        )
        .expect("seconds timestamp should be within valid range"),
    );

    buf.clear();

    write!(
        buf,
        "P-{:04}{:02}{:02}-{:02}{:02}{:02}-{trader_tag}-",
        now_utc.year(),
        now_utc.month(),
        now_utc.day(),
        now_utc.hour(),
        now_utc.minute(),
        now_utc.second(),
    )
    .expect("writing to String should not fail");
}

#[cfg(test)]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the value is seconds (not nanos/millis); a nanosecond timestamp passed as seconds overflows the valid range
  2. Range-check before calling: `-377705023201 <= secs <= 253402300799`
  3. Correct the clock/mock source to produce realistic epoch seconds

Example fix

// before
let secs = nanos / 1; // wrong units: nanos treated as seconds
let _ = generator.refresh_fixed_prefix(u64::try_from(secs).unwrap());
// after
let secs = nanos / 1_000_000_000; // convert nanos to seconds
assert!((-377705023201i64..=253402300799).contains(&secs));
let _ = generator.refresh_fixed_prefix(u64::try_from(secs).unwrap());
Defensive patterns

Strategy: validation

Validate before calling

fn in_jiff_range(secs: i64) -> bool { (-377705023201..=253402300799).contains(&secs) }

Prevention

When it happens

Trigger: Calling `refresh_fixed_prefix` for the PositionIdGenerator with epoch seconds outside jiff's valid range: above 253402300799 (year 9999) or below -377705023201.

Common situations: Mock clock fixtures using i64::MIN/MAX, timestamps corrupted by bad unit conversion (e.g. nanoseconds passed as seconds), or deserialized garbage values routed into the generator.

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 nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/ba1f528d4c1f58da. Report an issue: GitHub.