{"record":{"id":"ca5553d8cb753647","repo":"clockworklabs/SpacetimeDB","slug":"systemtime-predates-the-unix-epoch","errorCode":null,"errorMessage":"SystemTime predates the Unix epoch","messagePattern":"SystemTime predates the Unix epoch","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/sats/src/timestamp.rs","lineNumber":110,"sourceCode":"            Ok(positive) => SystemTime::UNIX_EPOCH\n                .checked_add(positive)\n                .expect(\"Timestamp with i64 microseconds since Unix epoch overflows SystemTime\"),\n            Err(negative) => SystemTime::UNIX_EPOCH\n                .checked_sub(negative)\n                .expect(\"Timestamp with i64 microseconds before Unix epoch overflows SystemTime\"),\n        }\n    }\n\n    /// Convert a [`SystemTime`] into a [`Timestamp`] which refers to approximately the same point in time.\n    ///\n    /// This conversion may panic if `system_time` is out of bounds for [`Duration`].\n    /// [`SystemTime`]'s range is larger than [`Timestamp`] on both Unix and Windows targets,\n    /// so times in the far past or far future may panic.\n    /// [`Timestamp`]'s range is approximately 292 years before and after the Unix epoch.\n    pub fn from_system_time(system_time: SystemTime) -> Self {\n        let duration = system_time\n            .duration_since(SystemTime::UNIX_EPOCH)\n            .expect(\"SystemTime predates the Unix epoch\");\n        Self::from_duration_since_unix_epoch(duration)\n    }\n\n    /// Returns the [`Duration`] delta between `self` and `earlier`, if `earlier` predates `self`.\n    ///\n    /// Returns `None` if `earlier` is strictly greater than `self`,\n    /// or if the difference between `earlier` and `self` overflows an `i64`.\n    pub fn duration_since(self, earlier: Timestamp) -> Option<Duration> {\n        self.time_duration_since(earlier)?.to_duration().ok()\n    }\n\n    /// Returns the [`TimeDuration`] delta between `self` and `earlier`.\n    ///\n    /// The result may be negative if `earlier` is actually later than `self`.\n    ///\n    /// Returns `None` if the subtraction overflows or underflows `i64` microseconds.\n    pub fn time_duration_since(self, earlier: Timestamp) -> Option<TimeDuration> {\n        let delta = self","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/sats/src/timestamp.rs#L92-L128","documentation":"Panic in `Timestamp::from_system_time`: `system_time.duration_since(UNIX_EPOCH).expect(\"SystemTime predates the Unix epoch\")` fires when the given `SystemTime` is before 1970-01-01, because `duration_since` returns an `Err` for pre-epoch times. Unlike `to_system_time`, which handles negatives via a checked branch, this constructor simply refuses pre-epoch input.","triggerScenarios":"Calling `Timestamp::from_system_time(t)` with a time earlier than the Unix epoch — e.g. a machine clock set before 1970 (broken RTC, VM clock bugs), archived/historical dates, or negative `Duration` arithmetic applied to `UNIX_EPOCH` (e.g. `UNIX_EPOCH - Duration::from_secs(10)`).","commonSituations":"Systems with dead CMOS batteries or NTP-starved VMs booting to pre-1970 dates; tests using `SystemTime::UNIX_EPOCH - x`; library code ingesting file timestamps or birthdates that legitimately predate 1970; containers with clock skews.","solutions":["At the call site, branch on `t.duration_since(SystemTime::UNIX_EPOCH)`: use `Ok(d) => Timestamp::from_duration_since_unix_epoch(d)` and handle `Err(e)` (e) explicitly (clamp, reject, or use the pre-epoch-capable constructor if one is added).","Fix the machine/VM clock (enable NTP; check RTC battery) if `SystemTime::now()` itself is pre-1970.","Reject or clamp pre-epoch input at your API boundary before it reaches this conversion.","Add a test feeding `UNIX_EPOCH - 1s` to catch regressions in time-handling paths."],"exampleFix":"// before: panics for pre-epoch times\nlet ts = Timestamp::from_system_time(t);\n\n// after: handle the pre-epoch case explicitly\nlet ts = match t.duration_since(SystemTime::UNIX_EPOCH) {\n    Ok(d) => Timestamp::from_duration_since_unix_epoch(d),\n    Err(e) => return Err(InvalidTime::pre_epoch(e.duration())),\n};","handlingStrategy":"validation","validationCode":"fn system_time_to_timestamp(t: SystemTime) -> Result<Timestamp, PreEpoch> {\n    match t.duration_since(SystemTime::UNIX_EPOCH) {\n        Ok(d) => Ok(Timestamp::from_duration_since_unix_epoch(d)),\n        Err(_) => Err(PreEpoch), // or clamp to Timestamp::UNIX_EPOCH\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass `UNIX_EPOCH - d` arithmetic results into from_system_time.","Run NTP and verify `date -u` on hosts/VMs that feed clock values.","Reject or clamp pre-epoch inputs at API boundaries."],"tags":["rust","spacetimedb","timestamp","systemtime","unix-epoch","clock","panic"],"backgroundTag":"pre-epoch-timestamp","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}