nautechsystems/nautilus_trader · error

{error}

Error message

{error}

What it means

run() refuses to start when a funding_rate error was captured earlier (self.funding_error is set), typically from an exchange module failing during funding settlement processing. The stored error is re-raised so the backtest never proceeds on a poisoned exchange state.

Source

Thrown at crates/backtest/src/engine.rs:694

    /// aligns its chunks to this boundary.
    ///
    /// Streaming workflow:
    /// 1. Add initial data and strategies
    /// 2. Loop: call `run(streaming=true)`, `clear_data()`, `add_data(next_batch)`
    /// 3. After all batches: call `end()` to finalize
    ///
    /// # Errors
    ///
    /// Returns an error if the backtest encounters an unrecoverable state.
    pub fn run(
        &mut self,
        start: Option<UnixNanos>,
        end: Option<UnixNanos>,
        run_config_id: Option<String>,
        streaming: bool,
    ) -> anyhow::Result<()> {
        if let Some(error) = &self.funding_error {
            anyhow::bail!("{error}");
        }
        self.check_module_errors()?;

        if let Err(e) = self.run_impl(start, end, run_config_id, streaming) {
            if self.funding_error.is_some()
                || self
                    .venues
                    .values()
                    .any(|exchange| exchange.borrow().has_module_error())
            {
                self.abort_run();
            }
            return Err(e);
        }

        // Finalize on non-streaming runs, or when a shutdown was triggered
        // at any point during the run (including the trailing settle, module,
        // and flush callbacks that execute after the main data loop) so the

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect and fix the underlying funding error (reset the engine with engine.reset() after diagnosing)
  2. Check funding rate data and SimulatedVenueConfig (funding rate settings) for the venue
  3. Create a fresh BacktestEngine if the previous run poisoned its state

Example fix

// before
engine.run()?;
// after
if engine_funding_error_occurred() {
    engine.reset();
}
engine.run()?;
Defensive patterns

Strategy: try-catch

Try / catch

match engine.run(start, end, run_config_id, streaming) {
    Err(e) if engine_has_funding_error() => {
        eprintln!("run blocked by prior funding error: {e}");
        engine.reset(); // after fixing funding data/config
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling engine.run() after a prior run or module pass recorded a funding error, e.g. a funding-rate calculation failure on an exchange during processing.

Common situations: Reusing one BacktestEngine across multiple runs where the first failed with a funding issue; funding rate data malformed for the venue/account config.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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