nautechsystems/nautilus_trader · error
Python on_order failed: {e}
Error message
Python on_order failed: {e} What it means
PyExecutionAlgorithm wraps a Python execution algorithm; when the Rust `ExecutionAlgorithm::on_order` trait method is invoked it dispatches into Python (`dispatch_on_order`). Any Python-side exception (or PyO3 boundary error) is re-wrapped as a Rust anyhow error with this message. It marks that the Python `on_order` callback itself failed, not the surrounding Rust pipeline.
Source
Thrown at crates/trading/src/python/algorithm.rs:393
fn core_mut(&mut self) -> &mut DataActorCore {
DataActorNative::core_mut(&mut self.inner_mut().core)
}
}
impl ExecutionAlgorithmNative for PyExecutionAlgorithm {
fn exec_algorithm_core(&self) -> &ExecutionAlgorithmCore {
&self.inner().core
}
fn exec_algorithm_core_mut(&mut self) -> &mut ExecutionAlgorithmCore {
&mut self.inner_mut().core
}
}
impl ExecutionAlgorithm for PyExecutionAlgorithm {
fn on_order(&mut self, order: OrderAny) -> anyhow::Result<()> {
self.dispatch_on_order(order)
.map_err(|e| anyhow::anyhow!("Python on_order failed: {e}"))
}
fn on_order_list(
&mut self,
order_list: OrderList,
orders: Vec<OrderAny>,
) -> anyhow::Result<()> {
if self
.has_python_override("on_order_list")
.map_err(|e| anyhow::anyhow!("Python override lookup failed: {e}"))?
{
return self
.dispatch_on_order_list(order_list, orders)
.map_err(|e| anyhow::anyhow!("Python on_order_list failed: {e}"));
}
for order in orders {
self.on_order(order)?;View on GitHub (pinned to 18893faf8b)
Solutions
- Read the chained `{e}` message; it contains the original Python traceback/exception and fix the Python on_order implementation.
- Reproduce the failing order in Python directly and run the on_order callback to get the full traceback.
- Verify the Python class actually defines on_order with the expected signature for the current pyo3-asyncio/bindings version.
- Confirm Python objects/imports are valid at construction time so the dispatch target exists.
Example fix
// Python side
class MyAlgo(ExecutionAlgorithm):
def on_order(self, order): # before: def on_order(self, order, ctx): -> TypeError
... Defensive patterns
Strategy: try-catch
Validate before calling
# Python: smoke-test the callback before registering the algorithm assert callable(getattr(algo, "on_order", None)), "on_order override missing"
Type guard
fn overrides_on_order(py_algo: &PyAny) -> pyo3::PyResult<bool> {
py_algo.call_method0("__class__")?.getattr("on_order")
.map(|_| true)
} Try / catch
match algo.on_order(order) {
Ok(()) => {},
Err(e) => log::error!("algorithm on_order failed: {e:#}"), // {e} carries the Python traceback
} Prevention
- Unit-test every Python ExecutionAlgorithm override in Python first with representative OrderAny data.
- Keep Python callback signatures exactly as the bindings expect (single order argument).
- Log the full anyhow chain ({e:#}) so the embedded Python traceback is visible.
When it happens
Trigger: Calling on_order (directly or via on_order_list fallback loop) when the Python handler raises an exception, has a bad signature, or the interpreter/object reference is invalid.
Common situations: A bug in a user-written Python ExecutionAlgorithm.on_order override (TypeError, AttributeError, unhandled domain error); calling a removed/renamed Python method; Python callback expecting different argument types than the OrderAny conversion provides.
Related errors
- Python on_order_list failed: {e}
- Failed to convert historical data to Python: unsupported typ
- Failed to convert instrument to Python: {e}
- Failed to convert batched deltas to Python: {e}
- Invalid book_snapshot_output: '{book_snapshot_output}'. Expe
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/429f361c3a8cc694.
Report an issue: GitHub.