nautechsystems/nautilus_trader · error
Python on_fault failed: {e}
Error message
Python on_fault failed: {e} What it means
This error is raised by the Rust-side `ExecutionAlgorithm` wrapper when the Python callback `on_fault` throws an exception. NautilusTrader dispatches lifecycle hooks from Rust into the user's Python subclass via `call_method0`; any `PyErr` is wrapped with `anyhow!("Python on_fault failed: {e}")` so the trader kernel receives a Rust `anyhow::Error`. The original Python traceback is preserved inside `{e}`.
Source
Thrown at crates/trading/src/python/algorithm.rs:580
fn on_reset(&mut self) -> anyhow::Result<()> {
ExecutionAlgorithm::on_reset(self)?;
self.dispatch_no_args("on_reset")
.map_err(|e| anyhow::anyhow!("Python on_reset failed: {e}"))
}
fn on_dispose(&mut self) -> anyhow::Result<()> {
self.dispatch_no_args("on_dispose")
.map_err(|e| anyhow::anyhow!("Python on_dispose failed: {e}"))
}
fn on_degrade(&mut self) -> anyhow::Result<()> {
self.dispatch_no_args("on_degrade")
.map_err(|e| anyhow::anyhow!("Python on_degrade failed: {e}"))
}
fn on_fault(&mut self) -> anyhow::Result<()> {
self.dispatch_no_args("on_fault")
.map_err(|e| anyhow::anyhow!("Python on_fault failed: {e}"))
}
fn on_time_event(&mut self, event: &TimeEvent) -> anyhow::Result<()> {
ExecutionAlgorithm::on_time_event(self, event)?;
self.dispatch_time_event(event)
.map_err(|e| anyhow::anyhow!("Python on_time_event failed: {e}"))
}
fn on_signal(&mut self, signal: &Signal) -> anyhow::Result<()> {
self.dispatch_on_signal(signal)
.map_err(|e| anyhow::anyhow!("Python on_signal failed: {e}"))
}
fn on_queue_state(&mut self, event: &QueueStateChanged) -> anyhow::Result<()> {
self.dispatch_on_queue_state(event)
.map_err(|e| anyhow::anyhow!("Python on_queue_state failed: {e}"))
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Read the chained Python traceback inside the error message to find the real exception raised in your `on_fault` override
- Wrap the body of your Python `on_fault` in try/except for recoverable conditions and log instead of raising
- Fix the underlying bug in `on_fault` (wrong attribute name, wrong call signature, unhandled state)
- Verify the method signature matches the base class: `def on_fault(self) -> None:` (no extra args)
- Pin your nautilus_trader version and check the changelog for callback API changes if a signature mismatch appears after upgrading
Example fix
# before
def on_fault(self):
self._orders[self._order_id].cancel() # raises KeyError
# after
def on_fault(self):
try:
self._orders[self._order_id].cancel()
except Exception as e:
self.log.error(f"Fault recovery failed: {e}") Defensive patterns
Strategy: try-catch
Validate before calling
import inspect assert isinstance(getattr(MyAlgo, 'on_fault', None), (types.FunctionType, types.MethodType)) sig = inspect.signature(MyAlgo.on_fault) assert len(sig.parameters) == 1 # self only
Type guard
def has_valid_on_fault(algo):
fn = getattr(algo, 'on_fault', None)
return callable(fn) and inspect.signature(fn).parameters.get('event') is None Try / catch
try:
algo.on_fault()
except Exception as e:
log.error(f"Algorithm on_fault dispatch failed: {e}") # original Python traceback is in str(e) Prevention
- Never let fault-recovery logic raise; log and continue instead
- Keep `on_fault` free of calls that depend on live connections or populated caches
- Match the base-class hook signature exactly when overriding
- Re-run the algorithm's backtest after each nautilus_trader upgrade to catch API drift
When it happens
Trigger: Calling `on_fault()` on a `PyExecutionAlgorithm` (e.g. via the trader moving the algorithm into the FAULTED state, or a direct `algo.on_fault()` call) when the user's Python subclass overrides `on_fault` and raises any exception (AttributeError, TypeError, unhandled data error, etc.).
Common situations: Custom execution algorithms whose `on_fault` handler references attributes not yet initialized, calls an API with the wrong signature after a nautilus_trader version upgrade, or performs fault recovery logic (e.g. cancelling orders) that fails because the client/connection is already down.
Related errors
- Python on_time_event failed: {e}
- Python on_signal failed: {e}
- Python on_queue_state failed: {e}
- Python on_socket_state failed: {e}
- Python on_pool_swap failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/22f4d7e22b9b514b.
Report an issue: GitHub.