nautechsystems/nautilus_trader · error

Python on_historical_mark_prices failed: {e}

Error message

Python on_historical_mark_prices failed: {e}

What it means

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.

Source

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

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

#[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;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the `{e}` part of the message for the underlying Python traceback and fix the bug in the Python `on_historical_mark_prices` handler.
  2. Confirm the Python actor defines `on_historical_mark_prices` with the correct signature and does not accidentally override it wrongly.
  3. Validate `MarkPriceUpdate` contents (instrument_id, price, price_type) before replay if your handler has assumptions about them.
  4. Add defensive checks/logging in the Python handler to identify which update triggers the failure.

Example fix

# before
def on_historical_mark_prices(self, mark_prices):
    for mp in mark_prices:
        price = mp.price  # AttributeError if field naming differs

# after
def on_historical_mark_prices(self, mark_prices):
    for mp in mark_prices:
        if mp is None or getattr(mp, 'price', None) is None:
            continue
        price = mp.price
Defensive patterns

Strategy: try-catch

Validate before calling

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

Type guard

def has_mark_price_handler(actor) -> bool:
    return callable(getattr(actor, 'on_historical_mark_prices', None))

Try / catch

if let Err(e) = actor.on_historical_mark_prices(&mark_prices) {
    log::error!("mark price dispatch failed: {e:#}");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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/3acbef1dd30a9471. Report an issue: GitHub.