clockworklabs/SpacetimeDB · warning
Timestamp with i64 microseconds before Unix epoch overflows…
Error message
Timestamp with i64 microseconds before Unix epoch overflows SystemTime
What it means
Panic in `Timestamp::to_system_time` for the negative branch: a pre-epoch Timestamp is converted with `UNIX_EPOCH.checked_sub(duration).expect("...before Unix epoch overflows SystemTime")`. If the negative offset is beyond what the platform `SystemTime` can represent (before its minimum), the checked subtraction returns None and this panics. Docs state they are unaware of a platform with a smaller range than Timestamp, so hits are rare.
Solutions
- Validate the Timestamp's magnitude (e.g. |micros| within 1970±9999 years) before `to_system_time()`.
- Trace where the pre-epoch Timestamp came from — legitimate historical data or a unit/sign bug in your time math.
- On narrow platforms, avoid the round-trip: keep values as Timestamp and convert only for display with an explicit range check.
- Centralize conversion in a checked helper returning Option instead of calling to_system_time directly.
Example fix
// before: panics on extreme pre-epoch values on narrow platforms
let st = ts.to_system_time();
// after: range-checked helper
fn checked_to_system_time(ts: Timestamp) -> Option<SystemTime> {
let micros = ts.micros_since_unix_epoch();
(micros.unsigned_abs() < 8_640_000_000_000_000 * 10_000).then(|| ts.to_system_time())
} Defensive patterns
Strategy: validation
Validate before calling
fn pre_epoch_to_system_time(ts: Timestamp) -> Option<SystemTime> {
let micros = ts.micros_since_unix_epoch();
(micros > -31_557_600_000_000 * 10_000 && micros < 0).then(|| ts.to_system_time())
} Prevention
- Range-check extreme pre-epoch Timestamps before to_system_time().
- Treat garbage negative Timestamps as a deserialization bug until proven otherwise.
- Prefer keeping time values as Timestamp and converting only at display edges.
When it happens
Trigger: Calling `to_system_time()` on a Timestamp far before 1970 (down to ~year -292k) on a platform whose `SystemTime` minimum is later than that (e.g. Windows epochs or 32-bit targets). Alternatively a corrupt/mis-decoded negative Timestamp (e.g. sign mishandling during deserialization) reaching this branch.
Common situations: Code converting arbitrary/historical dates or negative-delta arithmetic results to SystemTime; 32-bit or Windows targets with narrower time ranges; deserialization bugs producing garbage negative micros; fuzzed inputs.
Related errors
- Timestamp with i64 microseconds since Unix epoch overflows…
- Duration since Unix epoch overflows i64 microseconds
- SystemTime predates the Unix epoch
- Duration overflows i64 microseconds
- timestamp before unix epoch
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/748e886ec582304b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/sats/src/timestamp.rs:97
)
}
/// 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)
.expect("Timestamp with i64 microseconds before Unix epoch overflows SystemTime"),
}
}
/// Convert a [`SystemTime`] into a [`Timestamp`] which refers to approximately the same point in time.
///
/// This conversion may panic if `system_time` is out of bounds for [`Duration`].
/// [`SystemTime`]'s range is larger than [`Timestamp`] on both Unix and Windows targets,
/// so times in the far past or far future may panic.
/// [`Timestamp`]'s range is approximately 292 years before and after the Unix epoch.
pub fn from_system_time(system_time: SystemTime) -> Self {
let duration = system_time
.duration_since(SystemTime::UNIX_EPOCH)
.expect("SystemTime predates the Unix epoch");
Self::from_duration_since_unix_epoch(duration)
}
/// Returns the [`Duration`] delta between `self` and `earlier`, if `earlier` predates `self`.
///View on GitHub (pinned to 6dee26c6ef)