clockworklabs/SpacetimeDB · error

Duration since Unix epoch overflows i64 microseconds

Error message

Duration since Unix epoch overflows i64 microseconds

What it means

Panic in `Timestamp::from_duration_since_unix_epoch`: converting a `std::time::Duration` into a `Timestamp` (i64 microseconds since epoch) requires the microsecond count to fit in `i64` (~±292,471 years around 1970). `try_into().expect("Duration since Unix epoch overflows i64 microseconds")` panics beyond that. Documented as an intentional panic.

Solutions

  1. Log/inspect the incoming Duration at the call site to identify the arithmetic or unit bug (most common: ns vs ms vs µs confusion).
  2. Bound computed durations with `checked_mul`/`checked_add` and a sane maximum before building a Timestamp.
  3. Validate parsed numeric inputs (epoch values, offsets) against a plausible range (e.g. year 1..9999) before conversion.
  4. Add tests exercising extreme values through timestamp math.

Example fix

// before: unit confusion can overflow
let ts = Timestamp::from_duration_since_unix_epoch(Duration::from_nanos(input_ns));

// after: validate range first
let d = Duration::from_nanos(input_ns);
if d > Duration::from_secs(60 * 60 * 24 * 365 * 5000) { return Err(OutOfRange); }
let ts = Timestamp::from_duration_since_unix_epoch(d);
Defensive patterns

Strategy: validation

Validate before calling

const MAX_TS: Duration = Duration::from_secs(60 * 60 * 24 * 365 * 200_000);
fn checked_ts(d: Duration) -> Result<Timestamp, Overflow> {
    (d <= MAX_TS).then(|| Timestamp::from_duration_since_unix_epoch(d)).ok_or(Overflow)
}

Prevention

When it happens

Trigger: Calling `Timestamp::from_duration_since_unix_epoch(d)` with a Duration larger than ~292k years — typically from overflow-prone arithmetic (duration multiplication, summing intervals), `Duration::MAX`, or unvalidated parsed input. Everyday timestamps never hit this; the trigger is a computed/garbage Duration.

Common situations: Scheduling code computing far-future deadlines with `now + huge_offset`; parsing timestamps with wrong units (nanoseconds fed as milliseconds multiplies value by 1000 repeatedly); fuzz inputs; clock-offset calculations against `SystemTime::MAX`-style extremes.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/b4eb205d4ebc9f0e. Report an issue: GitHub.

Appendix: source

Thrown at crates/sats/src/timestamp.rs:78

    /// Returns `Err(duration_before_unix_epoch)` if `self` is before `Self::UNIX_EPOCH`.
    pub fn to_duration_since_unix_epoch(self) -> Result<Duration, Duration> {
        let micros = self.to_micros_since_unix_epoch();
        if micros >= 0 {
            Ok(Duration::from_micros(micros as u64))
        } else {
            Err(Duration::from_micros((-micros) as u64))
        }
    }

    /// Return a [`Timestamp`] which is [`Timestamp::UNIX_EPOCH`] plus `duration`.
    ///
    /// Panics if `duration.as_micros` overflows an `i64`
    pub fn from_duration_since_unix_epoch(duration: Duration) -> Self {
        Self::from_micros_since_unix_epoch(
            duration
                .as_micros()
                .try_into()
                .expect("Duration since Unix epoch overflows i64 microseconds"),
        )
    }

    /// Convert `self` into a [`SystemTime`] which refers to approximately the same point in time.
    ///
    /// This conversion may lose precision, as [`SystemTime`]'s prevision varies depending on platform.
    /// E.g. Unix targets have microsecond precision, but Windows only 100-microsecond precision.
    ///
    /// This conversion may panic if `self` is out of bounds for [`SystemTime`].
    /// We are not aware of any platforms for which [`SystemTime`] offers a smaller range than [`Timestamp`],
    /// but such a platform may exist.
    pub fn to_system_time(self) -> SystemTime {
        match self.to_duration_since_unix_epoch() {
            Ok(positive) => SystemTime::UNIX_EPOCH
                .checked_add(positive)
                .expect("Timestamp with i64 microseconds since Unix epoch overflows SystemTime"),
            Err(negative) => SystemTime::UNIX_EPOCH
                .checked_sub(negative)

View on GitHub (pinned to 6dee26c6ef)