nautechsystems/nautilus_trader · critical

Failed to set spread quote timer

Error message

Failed to set spread quote timer

What it means

The futures-spread quote aggregator sets a recurring timer on the live clock to drive quote generation; `set_timer_ns` returns a Result and the code `.expect`s success. A failure means the live clock refused or failed to register the timer (e.g. already in a bad state or internal clock error), which would silently stop spread quotes.

Source

Thrown at crates/data/src/aggregation.rs:2190

        }));

        let now_ns = self.clock.borrow().timestamp_ns();
        let interval_ns = DurationNanos::from_secs(interval_secs);
        let start_time =
            now_ns.floor(interval_ns) + DurationNanos::from_micros(self.quote_build_delay);
        let fire_immediately = now_ns == start_time;
        self.clock
            .borrow_mut()
            .set_timer_ns(
                &self.timer_name,
                interval_ns,
                Some(start_time),
                None,
                Some(callback),
                Some(true),
                Some(fire_immediately),
            )
            .expect("Failed to set spread quote timer");
    }

    /// Called when the timer fires (live mode). Builds and sends a spread quote using the timer event timestamp.
    pub fn on_timer_fire(&mut self, ts_event: UnixNanos) {
        if self.last_quotes.len() == self.leg_ids.len() {
            self.build_and_send_quote(ts_event);
        }
    }

    /// Stops the timer when in timer-driven mode.
    pub fn stop_timer(&mut self) {
        if self.update_interval_seconds.is_some()
            && self
                .clock
                .borrow()
                .timer_names()
                .contains(&self.timer_name.as_str())
        {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the spread aggregator is started/stopped exactly once per instrument; check for duplicate subscriptions of the same spread instrument
  2. Verify clean shutdown ordering: cancel timers/stop aggregators before tearing down the clock
  3. Inspect the inner clock error (wrap the expect with a match/log) to identify the exact `set_timer_ns` failure reason
  4. Upgrade/retry the subscription after a shutdown race; if reproducible, report as a NautilusTrader bug
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: ensure single registration per instrument before start
assert!(!active_spreads.contains(&instrument_id), "spread aggregator already started for {instrument_id}");

Try / catch

let result = std::panic::catch_unwind(|| agg.set_spread_quote_timer());
if result.is_err() { log::error!("spread quote timer setup failed"); }

Prevention

When it happens

Trigger: Calling the spread quote aggregator's timer setup (during spread subscription/startup in live mode) when `LiveClock::set_timer_ns` returns Err — e.g. registering a duplicate timer name, or the clock being shut down mid-setup.

Common situations: Starting a spread aggregator twice for the same instrument (duplicate timer name); shutting down the node while a spread subscription is being initialized; clock lifecycle races in live adapters.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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