nautechsystems/nautilus_trader · error
Python on_historical_bars failed: {e}
Error message
Python on_historical_bars failed: {e} What it means
This error wraps any failure raised by a Python data actor's `on_historical_bars` callback when the Rust actor core dispatches historical bars into Python. It is a bridging error: the Rust side succeeded in collecting the bars, but the Python handler (or something it calls) raised an exception, which is converted into an anyhow error with this prefix.
Source
Thrown at crates/common/src/python/actor.rs:1246
.map_err(|e| anyhow::anyhow!("Python on_historical_quotes failed: {e}"))
}
fn on_historical_trades(&mut self, trades: &[TradeTick]) -> anyhow::Result<()> {
self.dispatch_on_historical_trades(trades.to_vec())
.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]View on GitHub (pinned to 18893faf8b)
Solutions
- Read the full chained error message: the `{e}` portion contains the original Python traceback/exception; fix the bug it reports in your Python actor's `on_historical_bars`.
- Verify your Python actor actually defines `on_historical_bars` with the expected signature and does not shadow it with an incompatible override.
- Validate bar data (non-empty, correct Bar type, expected instrument IDs) before replaying historical data.
- Run the handler logic standalone in Python with the same bars to reproduce and debug the exception quickly.
Example fix
// Python side — before (fragile handler)
def on_historical_bars(self, bars):
closes = [b.close for b in bars]
avg = sum(closes) / len(closes) # ZeroDivisionError if bars is empty
// after
def on_historical_bars(self, bars):
if not bars:
return
closes = [b.close for b in bars]
avg = sum(closes) / len(closes) Defensive patterns
Strategy: try-catch
Validate before calling
# Python assert callable(getattr(actor, 'on_historical_bars', None)), 'actor missing on_historical_bars' assert bars, 'no bars to replay'
Type guard
def has_bar_handler(actor) -> bool:
return callable(getattr(actor, 'on_historical_bars', None)) Try / catch
match actor.on_historical_bars(bars) {
Err(e) => { log::error!("historical bars dispatch failed: {e:#}"); /* halt replay or skip actor */ }
Ok(()) => {}
} Prevention
- Keep Python handler code exception-free by validating inputs at the top of each handler
- Test actors in pure Python against sample bars before Rust integration
- Never shadow built-in callbacks with incompatible signatures
When it happens
Trigger: Calling the actor's historical-data dispatch path (e.g. via `PyDataActor::on_historical_bars` in crates/common/src/python/actor.rs:1246) when the registered Python object's `on_historical_bars` method raises an exception — bad bar data assumptions, unhandled None, a bug in user Python code, or a missing/renamed callback method.
Common situations: Backtesting or historical-data replay where a user-defined Python strategy actor processes `Bar` objects and its handler contains a Python bug (attribute error, division by zero, incompatible indicator input), or the callback was renamed/overridden incorrectly in a subclass.
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_mark_prices failed: {e}
- Python on_historical_index_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/c80df83aa938fe51.
Report an issue: GitHub.