nautechsystems/nautilus_trader · error

Python on_historical_index_prices failed: {e}

Error message

Python on_historical_index_prices failed: {e}

What it means

This error wraps any exception raised by a Python data actor's `on_historical_index_prices` callback when the Rust actor core dispatches historical index price updates into Python. It is a bridge error: the Rust side collected the updates fine, but the Python handler raised, and the exception is converted to an anyhow error with this prefix.

Source

Thrown at crates/common/src/python/actor.rs:1259

            .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}"))
    }
}

#[pymethods]
#[pyo3_stub_gen::derive::gen_stub_pymethods]
impl PyDataActor {
    /// Creates a new [`PyDataActor`] instance.
    ///
    /// Accepts `None` or any Python object. If the object is a [`DataActorConfig`]
    /// (or can be extracted as one via `from_py_object`), its values are used;
    /// otherwise the actor falls back to [`DataActorConfig::default()`].
    ///
    /// This permissive signature is required so that Python subclasses can pass a
    /// **custom** config dataclass to their `__init__`. The original object is retained
    /// here in `__new__`, which always receives the constructor arguments, so `.config`
    /// and registration see the config even when a subclass omits forwarding it to
    /// `super().__init__()`.
    #[new]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the `{e}` portion for the original Python exception and fix the bug in the Python `on_historical_index_prices` handler.
  2. Ensure the Python actor implements `on_historical_index_prices` with the expected signature; the base class will not silently provide one that suits your logic.
  3. Sanity-check the replayed `IndexPriceUpdate` data for None/zero prices or unexpected instrument IDs.
  4. Reproduce the failure by calling the Python handler directly with the offending update.

Example fix

# before
def on_historical_index_prices(self, index_prices):
    last = index_prices[-1].price  # IndexError when list is empty

# after
def on_historical_index_prices(self, index_prices):
    if not index_prices:
        return
    last = index_prices[-1].price
Defensive patterns

Strategy: try-catch

Validate before calling

# Python
assert callable(getattr(actor, 'on_historical_index_prices', None)), 'actor missing on_historical_index_prices'

Type guard

def has_index_price_handler(actor) -> bool:
    return callable(getattr(actor, 'on_historical_index_prices', None))

Try / catch

if let Err(e) = actor.on_historical_index_prices(&index_prices) {
    log::error!("index price dispatch failed: {e:#}");
}

Prevention

When it happens

Trigger: Calling `PyDataActor::on_historical_index_prices` (crates/common/src/python/actor.rs:1259) when the registered Python object's `on_historical_index_prices` method raises — user Python bug, missing/renamed callback, or invalid assumption about `IndexPriceUpdate` contents.

Common situations: Index/derivatives backtests replaying index prices where a Python strategy or indicator handler fails on unexpected values (None price, zero, wrong instrument id), or a Python subclass fails to implement the callback correctly.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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