{"record":{"id":"22f4d7e22b9b514b","repo":"nautechsystems/nautilus_trader","slug":"python-on-fault-failed-e-22f4d7","errorCode":null,"errorMessage":"Python on_fault failed: {e}","messagePattern":"Python on_fault failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/trading/src/python/algorithm.rs","lineNumber":580,"sourceCode":"    fn on_reset(&mut self) -> anyhow::Result<()> {\n        ExecutionAlgorithm::on_reset(self)?;\n        self.dispatch_no_args(\"on_reset\")\n            .map_err(|e| anyhow::anyhow!(\"Python on_reset failed: {e}\"))\n    }\n\n    fn on_dispose(&mut self) -> anyhow::Result<()> {\n        self.dispatch_no_args(\"on_dispose\")\n            .map_err(|e| anyhow::anyhow!(\"Python on_dispose failed: {e}\"))\n    }\n\n    fn on_degrade(&mut self) -> anyhow::Result<()> {\n        self.dispatch_no_args(\"on_degrade\")\n            .map_err(|e| anyhow::anyhow!(\"Python on_degrade failed: {e}\"))\n    }\n\n    fn on_fault(&mut self) -> anyhow::Result<()> {\n        self.dispatch_no_args(\"on_fault\")\n            .map_err(|e| anyhow::anyhow!(\"Python on_fault failed: {e}\"))\n    }\n\n    fn on_time_event(&mut self, event: &TimeEvent) -> anyhow::Result<()> {\n        ExecutionAlgorithm::on_time_event(self, event)?;\n        self.dispatch_time_event(event)\n            .map_err(|e| anyhow::anyhow!(\"Python on_time_event failed: {e}\"))\n    }\n\n    fn on_signal(&mut self, signal: &Signal) -> anyhow::Result<()> {\n        self.dispatch_on_signal(signal)\n            .map_err(|e| anyhow::anyhow!(\"Python on_signal failed: {e}\"))\n    }\n\n    fn on_queue_state(&mut self, event: &QueueStateChanged) -> anyhow::Result<()> {\n        self.dispatch_on_queue_state(event)\n            .map_err(|e| anyhow::anyhow!(\"Python on_queue_state failed: {e}\"))\n    }\n","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/trading/src/python/algorithm.rs#L562-L598","documentation":"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}`.","triggerScenarios":"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.).","commonSituations":"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.","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"],"exampleFix":"# before\ndef on_fault(self):\n    self._orders[self._order_id].cancel()  # raises KeyError\n\n# after\ndef on_fault(self):\n    try:\n        self._orders[self._order_id].cancel()\n    except Exception as e:\n        self.log.error(f\"Fault recovery failed: {e}\")","handlingStrategy":"try-catch","validationCode":"import inspect\nassert isinstance(getattr(MyAlgo, 'on_fault', None), (types.FunctionType, types.MethodType))\nsig = inspect.signature(MyAlgo.on_fault)\nassert len(sig.parameters) == 1  # self only","typeGuard":"def has_valid_on_fault(algo):\n    fn = getattr(algo, 'on_fault', None)\n    return callable(fn) and inspect.signature(fn).parameters.get('event') is None","tryCatchPattern":"try:\n    algo.on_fault()\nexcept Exception as e:\n    log.error(f\"Algorithm on_fault dispatch failed: {e}\")  # original Python traceback is in str(e)","preventionTips":["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"],"tags":["python","callback","lifecycle","rust","execution-algorithm"],"backgroundTag":"api-error-response","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}