{"record":{"id":"a651baa875d34ee2","repo":"nautechsystems/nautilus_trader","slug":"python-on-historical-index-prices-failed-e","errorCode":null,"errorMessage":"Python on_historical_index_prices failed: {e}","messagePattern":"Python on_historical_index_prices failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/python/actor.rs","lineNumber":1259,"sourceCode":"            .map_err(|e| anyhow::anyhow!(\"Python on_historical_funding_rates failed: {e}\"))\n    }\n\n    fn on_historical_bars(&mut self, bars: &[Bar]) -> anyhow::Result<()> {\n        self.dispatch_on_historical_bars(bars.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_bars failed: {e}\"))\n    }\n\n    fn on_historical_mark_prices(&mut self, mark_prices: &[MarkPriceUpdate]) -> anyhow::Result<()> {\n        self.dispatch_on_historical_mark_prices(mark_prices.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_mark_prices failed: {e}\"))\n    }\n\n    fn on_historical_index_prices(\n        &mut self,\n        index_prices: &[IndexPriceUpdate],\n    ) -> anyhow::Result<()> {\n        self.dispatch_on_historical_index_prices(index_prices.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_index_prices failed: {e}\"))\n    }\n}\n\n#[pymethods]\n#[pyo3_stub_gen::derive::gen_stub_pymethods]\nimpl PyDataActor {\n    /// Creates a new [`PyDataActor`] instance.\n    ///\n    /// Accepts `None` or any Python object. If the object is a [`DataActorConfig`]\n    /// (or can be extracted as one via `from_py_object`), its values are used;\n    /// otherwise the actor falls back to [`DataActorConfig::default()`].\n    ///\n    /// This permissive signature is required so that Python subclasses can pass a\n    /// **custom** config dataclass to their `__init__`. The original object is retained\n    /// here in `__new__`, which always receives the constructor arguments, so `.config`\n    /// and registration see the config even when a subclass omits forwarding it to\n    /// `super().__init__()`.\n    #[new]","sourceCodeStart":1241,"sourceCodeEnd":1277,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/python/actor.rs#L1241-L1277","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ndef on_historical_index_prices(self, index_prices):\n    last = index_prices[-1].price  # IndexError when list is empty\n\n# after\ndef on_historical_index_prices(self, index_prices):\n    if not index_prices:\n        return\n    last = index_prices[-1].price","handlingStrategy":"try-catch","validationCode":"# Python\nassert callable(getattr(actor, 'on_historical_index_prices', None)), 'actor missing on_historical_index_prices'","typeGuard":"def has_index_price_handler(actor) -> bool:\n    return callable(getattr(actor, 'on_historical_index_prices', None))","tryCatchPattern":"if let Err(e) = actor.on_historical_index_prices(&index_prices) {\n    log::error!(\"index price dispatch failed: {e:#}\");\n}","preventionTips":["Guard against empty update lists in Python handlers","Check for None/zero prices before arithmetic","Unit-test index price handlers with edge-case data"],"tags":["python","rust-bridge","actor","index-price","callback"],"backgroundTag":"api-request-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}