clockworklabs/SpacetimeDB · error
Duration since Unix epoch overflows i64 microseconds
Error message
Duration since Unix epoch overflows i64 microseconds
What it means
`Timestamp` is micros since the Unix epoch stored in an i64 (~±292 years around 1970). `from_duration_since_unix_epoch` panics when `duration.as_micros()` overflows i64 — i.e. a Duration longer than roughly 292,471 years. Normal wall-clock conversion never approaches this; the trigger is almost always a units bug or an attacker-controlled duration.
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 524b4487d9)
Solutions
- Fix the unit arithmetic that produced the oversized Duration.
- Validate external durations before converting: `d.as_micros() <= i64::MAX as u128`.
- Use `try_into()` on the micros and handle the Err as a proper error value instead of panicking.
Example fix
// before let ts = Timestamp::from_duration_since_unix_epoch(Duration::from_secs(60 * 60 * 24 * 365 * 300_000)); // panics // after: checked conversion the caller can handle let micros: i64 = duration.as_micros().try_into().map_err(|_| "duration out of range")?; let ts = Timestamp::from_micros_since_unix_epoch(micros);
Defensive patterns
Strategy: validation
Validate before calling
if duration.as_micros() > i64::MAX as u128 {
return Err("duration exceeds Timestamp range".into());
}
let ts = Timestamp::from_duration_since_unix_epoch(duration); Prevention
- Fix unit arithmetic at the source; i64-micros overflow implies a bug or hostile input.
- Range-check untrusted durations at the trust boundary.
- Prefer Timestamp::from_micros_since_unix_epoch with a checked cast so errors are values.
When it happens
Trigger: Calling `Timestamp::from_duration_since_unix_epoch(d)` with d produced by wrong unit multipliers (nanos treated as micros and scaled again), unvalidated input, or runaway accumulation loops.
Common situations: Date arithmetic bugs in expiry/timeout logic; deserializing untrusted durations from API payloads or config; tests with exaggerated constants.
Related errors
- Duration overflows i64 microseconds
- Timestamp with i64 microseconds since Unix epoch overflows S
- Timestamp with i64 microseconds before Unix epoch overflows
- SystemTime predates the Unix epoch
- timestamp before unix epoch
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/b4eb205d4ebc9f0e.
Report an issue: GitHub.