{"record":{"id":"8562c3d48ca4ece8","repo":"nautechsystems/nautilus_trader","slug":"python-on-time-event-failed-e-8562c3","errorCode":null,"errorMessage":"Python on_time_event failed: {e}","messagePattern":"Python on_time_event failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/trading/src/python/strategy.rs","lineNumber":1107,"sourceCode":"    fn on_fault(&mut self) -> anyhow::Result<()> {\n        self.dispatch_on_fault()\n            .map_err(|e| anyhow::anyhow!(\"Python on_fault failed: {e}\"))\n    }\n\n    fn on_save(&self) -> anyhow::Result<IndexMap<String, Vec<u8>>> {\n        self.dispatch_on_save()\n            .map_err(|e| anyhow::anyhow!(\"Python on_save failed: {e}\"))\n    }\n\n    fn on_load(&mut self, state: IndexMap<String, Vec<u8>>) -> anyhow::Result<()> {\n        self.dispatch_on_load(&state)\n            .map_err(|e| anyhow::anyhow!(\"Python on_load failed: {e}\"))\n    }\n\n    fn on_time_event(&mut self, event: &TimeEvent) -> anyhow::Result<()> {\n        route_time_event(self, event);\n        self.dispatch_on_time_event(event)\n            .map_err(|e| anyhow::anyhow!(\"Python on_time_event failed: {e}\"))\n    }\n\n    #[allow(unused_variables)]\n    fn on_data(&mut self, data: &CustomData) -> anyhow::Result<()> {\n        Python::attach(|py| {\n            let py_data: Py<PyAny> = Py::new(py, data.clone())?.into_any();\n            self.dispatch_on_data(py_data)\n                .map_err(|e| anyhow::anyhow!(\"Python on_data failed: {e}\"))\n        })\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)","sourceCodeStart":1089,"sourceCodeEnd":1125,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/trading/src/python/strategy.rs#L1089-L1125","documentation":"The strategy's Python-level `on_time_event` (timer/alarm) callback raised an exception. Before dispatch, `route_time_event(self, event)` routes the event, then `dispatch_on_time_event` invokes the Python method; any exception is wrapped at strategy.rs:1107 as `Python on_time_event failed: {e}`. Because timers fire on a schedule, this error repeats every interval until fixed.","triggerScenarios":"A timer registered via `clock.set_timer(...)` (or an interval/time handler) fires and the Python handler raises — e.g. division by zero in a periodic indicator update, calling a market-data method with no data yet, or an exception in code the timer lambda captured.","commonSituations":"Timers that fire before warm-up data exists; timer callbacks using `self.last_price` that is still None; exceptions inside repeated timers that spam logs and may halt the strategy; timer name/wiring mistakes where the handler for a different timer raises.","solutions":["Inspect `{e}` for the Python exception and fix the handler body; note the TimeEvent `name` to identify which timer fired.","Add early-return guards for not-yet-available state (e.g. `if self.last_price is None: return`).","Wrap periodic timer logic in try/except with logging so one bad tick does not kill the strategy loop.","Check `route_time_event` wiring: ensure each registered timer name maps to the intended handler."],"exampleFix":"// before\ndef on_time_event(self, event):\n    ret = (self.last_close - self.ema) / self.ema  # ZeroDivisionError on first ticks\n\n// after\ndef on_time_event(self, event):\n    if self.ema is None or self.ema == 0:\n        return\n    ret = (self.last_close - self.ema) / self.ema","handlingStrategy":"try-catch","validationCode":"def safe_timer(handler):\n    def wrapper(event):\n        try:\n            handler(event)\n        except Exception as e:\n            log.error(f\"timer {getattr(event, 'name', '?')} failed: {e}\")\n    return wrapper\n# register: clock.set_timer(\"tick\", interval, callback=safe_timer(self.on_time_event))","typeGuard":"def is_warm(self, *attrs):\n    return all(getattr(self, a, None) is not None for a in attrs)","tryCatchPattern":"def on_time_event(self, event):\n    try:\n        self._periodic_update()\n    except Exception as e:\n        self.log.error(f\"timer {event.name} handler failed: {e}\")","preventionTips":["Guard warm-up state (None prices/indicators) with early returns.","Wrap periodic timer bodies in try/except so one bad tick doesn't repeat-fail.","Log event.name to map failures to the specific timer.","Keep timer handlers fast and side-effect isolated from trading logic errors."],"tags":["python","strategy","timer","callback"],"backgroundTag":"python-callback-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}