nautechsystems/nautilus_trader · error

Timer '{name}' alert time {} was in the past (current time i

Error message

Timer '{name}' alert time {} was in the past (current time is {ts_now})

What it means

set_time_alert_ns validates that a one-shot timer alert time is in the future. When the alert time is already past, the live clock variant rejects the request via anyhow::bail so the caller knows the alert can never fire at the requested instant; the test/backtest clock variant instead silently adjusts the alert to now for immediate firing (per the warn branch). This prevents scheduling an alert that would be missed.

Source

Thrown at crates/common/src/clock.rs:808

    name: &str,
    mut alert_time_ns: UnixNanos,
    allow_past: Option<bool>,
    ts_now: UnixNanos,
) -> anyhow::Result<(Ustr, UnixNanos)> {
    check_valid_string_utf8(name, stringify!(name))?;

    let name = Ustr::from(name);
    let allow_past = allow_past.unwrap_or(true);

    if alert_time_ns < ts_now {
        if allow_past {
            log::warn!(
                "Timer '{name}' alert time {} was in the past, adjusted to current time for immediate firing",
                alert_time_ns.to_rfc3339(),
            );
            alert_time_ns = ts_now;
        } else {
            anyhow::bail!(
                "Timer '{name}' alert time {} was in the past (current time is {ts_now})",
                alert_time_ns.to_rfc3339(),
            );
        }
    }

    Ok((name, alert_time_ns))
}

/// Validates and normalizes parameters for an interval timer.
///
/// A missing or zero `start_time_ns` resolves to `ts_now`. `allow_past` defaults to `true`, and
/// `fire_immediately` defaults to `false`. Returns the interned name, normalized start and stop
/// times, and resolved flag values.
///
/// # Errors
///
/// Returns an error if:

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Clamp or recompute the alert time before calling: if alert_time_ns <= clock.timestamp_ns(), either skip or use the current time plus a small delta.
  2. Pass a time source consistent with the clock: derive alert times from clock.timestamp_ns(), not wall time from another machine.
  3. Use a TestClock/backtest clock if replaying historical alerts, where past alerts are adjusted rather than rejected.
  4. Catch the error and log/skip the alert if firing in the past is meaningless for your strategy.

Example fix

// before
clock.set_time_alert_ns("my_alert", stale_alert_time_ns);
// after
let now = clock.timestamp_ns();
let alert_time_ns = if stale_alert_time_ns <= now { now + 1_000_000_000 } else { stale_alert_time_ns };
clock.set_time_alert_ns("my_alert", alert_time_ns);
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_future_alert(clock: &dyn Clock, name: &str, alert_time_ns: u64) -> anyhow::Result<u64> {
    let now = clock.timestamp_ns();
    if alert_time_ns <= now {
        anyhow::bail!("alert '{name}' time {alert_time_ns} is in the past (now {now})");
    }
    Ok(alert_time_ns)
}

Try / catch

match clock.set_time_alert_ns(name, alert_time) {
    Ok(()) => {},
    Err(e) if e.to_string().contains("was in the past") => log::warn!("skipping stale alert: {e}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling set_time_alert_ns (or its Cython wrapper) on a LiveClock with an alert_time_ns earlier than the current clock timestamp, with the allow-past adjustment disabled.

Common situations: Replaying a stored strategy config whose alert timestamps are stale; system clock skew between machines; computing an alert from an old event timestamp in live trading; DST/manual clock changes pushing 'now' past a precomputed alert time.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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