{"record":{"id":"423b6c7406726044","repo":"nautechsystems/nautilus_trader","slug":"timer-name-first-event-time-exceeds-unixnanos","errorCode":null,"errorMessage":"Timer '{name}' first event time exceeds UnixNanos range","messagePattern":"Timer '(.+?)' first event time exceeds UnixNanos range","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/clock.rs","lineNumber":857,"sourceCode":"    fire_immediately: Option<bool>,\n    ts_now: UnixNanos,\n) -> anyhow::Result<(Ustr, UnixNanos, Option<UnixNanos>, bool, bool)> {\n    check_valid_string_utf8(name, stringify!(name))?;\n    check_positive_u64(interval_ns.as_u64(), stringify!(interval_ns))?;\n\n    let name = Ustr::from(name);\n    let allow_past = allow_past.unwrap_or(true);\n    let fire_immediately = fire_immediately.unwrap_or(false);\n\n    let start_time_ns = start_time_ns\n        .filter(|start_time_ns| *start_time_ns != 0)\n        .unwrap_or(ts_now);\n\n    let next_event_time = if fire_immediately {\n        start_time_ns\n    } else {\n        start_time_ns.checked_add(interval_ns).ok_or_else(|| {\n            anyhow::anyhow!(\"Timer '{name}' first event time exceeds UnixNanos range\")\n        })?\n    };\n\n    if !allow_past && next_event_time < ts_now {\n        anyhow::bail!(\n            \"Timer '{name}' next event time {} would be in the past (current time is {ts_now})\",\n            next_event_time.to_rfc3339(),\n        );\n    }\n\n    if let Some(stop_time) = stop_time_ns {\n        if stop_time <= start_time_ns {\n            anyhow::bail!(\n                \"Timer '{name}' stop time {} must be after start time {}\",\n                stop_time.to_rfc3339(),\n                start_time_ns.to_rfc3339(),\n            );\n        }","sourceCodeStart":839,"sourceCodeEnd":875,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/clock.rs#L839-L875","documentation":"NautilusTrader's clock validates that a timer's first fire time fits in the UnixNanos (i64 nanoseconds) domain. When registering a timer whose start_time_ns plus interval_ns would overflow the nanosecond range, the checked addition fails and this error is returned instead of silently wrapping. It protects downstream time arithmetic from overflow-corrected garbage timestamps.","triggerScenarios":"Calling set_time_alert_ns/set_timer_ns with an interval_ns so large that start_time_ns + interval_ns exceeds i64::MAX nanoseconds (~year 2262); e.g. passing an interval expressed in milliseconds or seconds by mistake, or an absurdly long duration near u64/i64 nanosecond limits.","commonSituations":"Unit-conversion mistakes (passing nanoseconds constant like 86_400_000_000_000 multiplied again, or using Duration::MAX-style values), scheduling timers intended to 'never fire' by using a huge interval, misconfigured timeout config parsed into the wrong unit.","solutions":["Reduce the timer interval so start_time_ns + interval_ns stays below ~9.2e18 nanoseconds","Verify units: interval_ns must already be in nanoseconds; convert seconds/ms with Duration::from_secs(...).as_nanos() as u64","If the intent is a far-future/never-firing timer, use a smaller sentinel interval or cancel the timer explicitly instead","Check that start_time_ns itself is a plausible current-time UnixNanos value and not already near the limit"],"exampleFix":"// before\nclock.set_timer_ns(\"poll\", u64::MAX, None, None, None, false, false, None)?;\n// after\nlet one_hour_ns = std::time::Duration::from_secs(3600).as_nanos() as u64;\nclock.set_timer_ns(\"poll\", one_hour_ns, None, None, None, false, false, None)?;","handlingStrategy":"validation","validationCode":"let max_interval: u64 = (i64::MAX as u128 - start_time_ns as u128) as u64;\nassert!(interval_ns <= max_interval, \"timer interval overflows UnixNanos\");","typeGuard":null,"tryCatchPattern":"match clock.set_timer_ns(name, interval, None, None, None, false, false, None) {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"exceeds UnixNanos range\") => {\n        log::error!(\"interval too large for nanosecond domain: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always convert durations to nanoseconds via Duration::as_nanos() rather than hand-written constants","Reject intervals beyond a sane maximum (e.g. > 100 years) at config load time","Never use u64::MAX-style sentinels as 'infinite' intervals"],"tags":["timer","overflow","unixnanos","rust"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}