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
- Read the `{e}` portion for the original Python exception and fix the bug in the Python `on_historical_index_prices` handler.
- 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.
- Sanity-check the replayed `IndexPriceUpdate` data for None/zero prices or unexpected instrument IDs.
- 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
- Guard against empty update lists in Python handlers
- Check for None/zero prices before arithmetic
- Unit-test index price handlers with edge-case data
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
- Python on_historical_bars failed: {e}
- Python on_historical_mark_prices failed: {e}
- Python on_order failed: {e}
- Python on_order_list failed: {e}
- Python on_signal failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a651baa875d34ee2.
Report an issue: GitHub.