{"record":{"id":"3acbef1dd30a9471","repo":"nautechsystems/nautilus_trader","slug":"python-on-historical-mark-prices-failed-e","errorCode":null,"errorMessage":"Python on_historical_mark_prices failed: {e}","messagePattern":"Python on_historical_mark_prices failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/python/actor.rs","lineNumber":1251,"sourceCode":"            .map_err(|e| anyhow::anyhow!(\"Python on_historical_trades failed: {e}\"))\n    }\n\n    fn on_historical_funding_rates(\n        &mut self,\n        funding_rates: &[FundingRateUpdate],\n    ) -> anyhow::Result<()> {\n        self.dispatch_on_historical_funding_rates(funding_rates.to_vec())\n            .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;","sourceCodeStart":1233,"sourceCodeEnd":1269,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/python/actor.rs#L1233-L1269","documentation":"This error wraps any exception raised by a Python data actor's `on_historical_mark_prices` callback when the Rust actor core dispatches historical mark price updates into Python. The Rust dispatch itself succeeded; the failure originates inside the Python handler and is re-raised as an anyhow error with this prefix.","triggerScenarios":"Calling `PyDataActor::on_historical_mark_prices` (crates/common/src/python/actor.rs:1251) when the Python object's `on_historical_mark_prices` method raises — typically a bug in user Python code, wrong signature, or assumption about the `MarkPriceUpdate` payload shape.","commonSituations":"Derivatives backtests replaying mark price updates where a Python strategy actor mishandles the payload (accessing fields that are None, wrong price precision assumptions, an indicator that rejects mark-price inputs), or a subclass overriding the callback with an incompatible signature.","solutions":["Inspect the `{e}` part of the message for the underlying Python traceback and fix the bug in the Python `on_historical_mark_prices` handler.","Confirm the Python actor defines `on_historical_mark_prices` with the correct signature and does not accidentally override it wrongly.","Validate `MarkPriceUpdate` contents (instrument_id, price, price_type) before replay if your handler has assumptions about them.","Add defensive checks/logging in the Python handler to identify which update triggers the failure."],"exampleFix":"# before\ndef on_historical_mark_prices(self, mark_prices):\n    for mp in mark_prices:\n        price = mp.price  # AttributeError if field naming differs\n\n# after\ndef on_historical_mark_prices(self, mark_prices):\n    for mp in mark_prices:\n        if mp is None or getattr(mp, 'price', None) is None:\n            continue\n        price = mp.price","handlingStrategy":"try-catch","validationCode":"# Python\nassert callable(getattr(actor, 'on_historical_mark_prices', None)), 'actor missing on_historical_mark_prices'","typeGuard":"def has_mark_price_handler(actor) -> bool:\n    return callable(getattr(actor, 'on_historical_mark_prices', None))","tryCatchPattern":"if let Err(e) = actor.on_historical_mark_prices(&mark_prices) {\n    log::error!(\"mark price dispatch failed: {e:#}\");\n}","preventionTips":["Validate MarkPriceUpdate fields before use in handlers","Use getattr guards for optional fields in Python","Replay a small sample of mark prices in Python tests first"],"tags":["python","rust-bridge","actor","mark-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"}