nautechsystems/nautilus_trader · error · anyhow::Error

system clock before Unix epoch: {e}

Error message

system clock before Unix epoch: {e}

What it means

build_event_slugs takes the current time via SystemTime::now().duration_since(UNIX_EPOCH) to compute the current up/down market period. This error is thrown when the system clock reports a time before the Unix epoch (a negative duration), which cannot be represented as u64 seconds, so slug construction must fail rather than compute a bogus period.

Source

Thrown at crates/adapters/polymarket/src/config.rs:106

});

impl Default for PolymarketUpDownEventSlugConfig {
    fn default() -> Self {
        Self::builder().build()
    }
}

impl PolymarketUpDownEventSlugConfig {
    /// Builds event slugs using the current system time.
    ///
    /// # Errors
    ///
    /// Returns an error if the interval or period count is zero, all assets are
    /// blank, or the configured offset resolves before the Unix epoch.
    pub fn build_event_slugs(&self) -> anyhow::Result<Vec<String>> {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .map_err(|e| anyhow::anyhow!("system clock before Unix epoch: {e}"))?
            .as_secs();
        self.build_event_slugs_at_unix_secs(now)
    }

    fn build_event_slugs_at_unix_secs(&self, unix_secs: u64) -> anyhow::Result<Vec<String>> {
        if self.interval_mins == 0 {
            anyhow::bail!("event_slug_builder.interval_mins must be positive");
        }

        if self.periods == 0 {
            anyhow::bail!("event_slug_builder.periods must be positive");
        }

        let assets = self.normalized_assets();
        if assets.is_empty() {
            anyhow::bail!("event_slug_builder.assets must include at least one non-empty asset");
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Sync the system clock (systemctl restart systemd-timesyncd / ntpdate / wait for chronyd) and retry.
  2. Check `date -u` on the host; if the year is before 1970, fix the RTC/timezone configuration.
  3. In containers, ensure the host clock is correct and time namespacing isn't skewing the container view.
  4. If your environment deliberately fakes time, call the deterministic sibling build_event_slugs_at_unix_secs with an explicit timestamp instead.

Example fix

// before: host clock at 1969
let slugs = config.build_event_slugs()?;
// after: fix host time, or inject time deterministically
sudo chronyc makestep
let slugs = config.build_event_slugs_at_unix_secs(explicit_unix_secs)?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: verify the host clock is sane before building slugs
fn clock_is_sane() -> bool {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .map(|d| d.as_secs() > 1_600_000_000) // after Sep 2020
        .unwrap_or(false)
}

Try / catch

match config.build_event_slugs() {
    Ok(slugs) => use(slugs),
    Err(e) if e.to_string().contains("Unix epoch") => {
        sync_system_clock(); // ntpdate / chronyc makestep
        retry(config.build_event_slugs())
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling PolymarketConfig::build_event_slugs while the host clock is set earlier than 1970-01-01T00:00:00Z — e.g. a VM/container without RTC that hasn't synced NTP, or a clock reset.

Common situations: Fresh VMs or embedded devices booting with default BIOS/CMOS dates; containers started before NTP sync; clock drift or deliberate time skew in CI sandboxes.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/e41fcdcce6683bbc. Report an issue: GitHub.