nautechsystems/nautilus_trader · error · anyhow::Error

Python on_historical_bars failed: {e}

Error message

Python on_historical_bars failed: {e}

What it means

This error wraps any failure while the Rust engine invokes the strategy's Python `on_historical_bars` callback with a batch of Bar objects. Conversion of each Bar to a Python object or an exception raised inside the user's Python handler is captured and re-raised as `Python on_historical_bars failed: {e}`.

Source

Thrown at crates/trading/src/python/strategy.rs:1252

            .map_err(|e| anyhow::anyhow!("Python on_historical_quotes failed: {e}"))
    }

    fn on_historical_trades(&mut self, trades: &[TradeTick]) -> anyhow::Result<()> {
        self.dispatch_on_historical_trades(trades.to_vec())
            .map_err(|e| anyhow::anyhow!("Python on_historical_trades failed: {e}"))
    }

    fn on_historical_funding_rates(
        &mut self,
        funding_rates: &[FundingRateUpdate],
    ) -> anyhow::Result<()> {
        self.dispatch_on_historical_funding_rates(funding_rates.to_vec())
            .map_err(|e| anyhow::anyhow!("Python on_historical_funding_rates failed: {e}"))
    }

    fn on_historical_bars(&mut self, bars: &[Bar]) -> anyhow::Result<()> {
        self.dispatch_on_historical_bars(bars.to_vec())
            .map_err(|e| anyhow::anyhow!("Python on_historical_bars failed: {e}"))
    }

    fn on_historical_mark_prices(&mut self, mark_prices: &[MarkPriceUpdate]) -> anyhow::Result<()> {
        self.dispatch_on_historical_mark_prices(mark_prices.to_vec())
            .map_err(|e| anyhow::anyhow!("Python on_historical_mark_prices failed: {e}"))
    }

    fn on_historical_index_prices(
        &mut self,
        index_prices: &[IndexPriceUpdate],
    ) -> anyhow::Result<()> {
        self.dispatch_on_historical_index_prices(index_prices.to_vec())
            .map_err(|e| anyhow::anyhow!("Python on_historical_index_prices failed: {e}"))
    }
}

fn state_to_pydict(py: Python<'_>, state: &IndexMap<String, Vec<u8>>) -> PyResult<Py<PyDict>> {
    let py_state = PyDict::new(py);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the `{e}` message for the underlying Python exception raised in your `on_historical_bars` override and fix it.
  2. Confirm the override signature `def on_historical_bars(self, bars)` matches exactly.
  3. Handle the empty-bars case before processing.
  4. Check that any indicators or types used in the handler accept the Bar objects passed.

Example fix

// before
def on_historical_bars(self, bars):
    self.fast.update(bars[-1])
// after
def on_historical_bars(self, bars):
    if not bars:
        return
    for bar in bars:
        self.fast.update(bar)
Defensive patterns

Strategy: try-catch

Validate before calling

def _safe_on_historical_bars(self, bars):
    if bars is None or len(bars) == 0:
        return
    assert all(hasattr(b, 'open') and hasattr(b, 'close') for b in bars)

Type guard

def is_bar_list(obj):
    return isinstance(obj, (list, tuple)) and all(hasattr(b, 'close') for b in obj)

Try / catch

def on_historical_bars(self, bars):
    try:
        for bar in bars:
            self.indicators.update(bar)
    except Exception as e:
        self.log.error(f'Failed processing historical bars: {e}', exc_info=True)

Prevention

When it happens

Trigger: Historical bar data (e.g. from a request_bars response) is delivered to a Python strategy whose `on_historical_bars` override raises, or whose bars fail the Rust→Python conversion.

Common situations: User handler assumes a specific bar count or bar fields; calling indicators with wrong types; exceptions like KeyError/TypeError in the override; requesting bars for an instrument with no data and mishandling the empty list.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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