{"record":{"id":"e21013e04ef663bd","repo":"nautechsystems/nautilus_trader","slug":"python-on-reset-failed-e-e21013","errorCode":null,"errorMessage":"Python on_reset failed: {e}","messagePattern":"Python on_reset failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/trading/src/python/strategy.rs","lineNumber":1076,"sourceCode":"    fn on_start(&mut self) -> anyhow::Result<()> {\n        Strategy::on_start(self)?;\n        self.dispatch_on_start()\n            .map_err(|e| anyhow::anyhow!(\"Python on_start failed: {e}\"))\n    }\n\n    fn on_stop(&mut self) -> anyhow::Result<()> {\n        self.dispatch_on_stop()\n            .map_err(|e| anyhow::anyhow!(\"Python on_stop failed: {e}\"))\n    }\n\n    fn on_resume(&mut self) -> anyhow::Result<()> {\n        self.dispatch_on_resume()\n            .map_err(|e| anyhow::anyhow!(\"Python on_resume failed: {e}\"))\n    }\n\n    fn on_reset(&mut self) -> anyhow::Result<()> {\n        self.dispatch_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_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_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_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>>> {","sourceCodeStart":1058,"sourceCodeEnd":1094,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/trading/src/python/strategy.rs#L1058-L1094","documentation":"This error wraps any Python exception raised by the strategy's user-implemented `on_reset()` callback. The Rust `DataActor::on_reset` dispatches to the Python instance via `call_method0(py, \"on_reset\")` (crates/trading/src/python/strategy.rs:356-361) and re-wraps any `PyErr` as `anyhow::anyhow!(\"Python on_reset failed: {e}\")`. Reset is used to return the actor to a clean state (e.g. between backtest runs), so a failure here can poison subsequent runs with stale state.","triggerScenarios":"Calling `strategy.reset()` (engine reset, backtest re-run, or post-fault recovery) when the Python subclass's `on_reset()` raises: e.g. clearing state containers that were never initialized, releasing resources already released, or any bug in user reset logic.","commonSituations":"Backtest loops where the second run's `on_reset` hits state assumptions from the first run, deleting files or keys that don't exist, or resetting attributes that were never set because the strategy never started.","solutions":["Read the chained Python traceback to find the raising line in `on_reset`.","Initialize all resettable attributes in `__init__` (e.g. `self._orders = {}`) so reset can safely clear them.","Use tolerant clears (`dict.pop`, `getattr` with defaults, `contextlib.suppress`) in `on_reset`.","Make `on_reset` idempotent and test it in a start -> reset -> start cycle."],"exampleFix":"// before (strategy.py)\ndef on_reset(self):\n    self.cache.delete(self._cache_key)  # raises if never created\n\n// after\ndef on_reset(self):\n    self._orders = {}\n    self.cache.delete(self._cache_key) if self.cache.check(self._cache_key) else None","handlingStrategy":"try-catch","validationCode":"# before reset in a backtest loop\nmissing = [a for a in (\"_orders\", \"_positions\") if not hasattr(strategy, a)]\nassert not missing, f\"uninitialized resettable attrs: {missing}\"","typeGuard":"def safely_reset(obj, attr, default):\n    if hasattr(obj, attr):\n        setattr(obj, attr, default)","tryCatchPattern":"def on_reset(self):\n    with contextlib.suppress(Exception):\n        self.cache.delete(self._cache_key)\n    self._orders = {}\n    self._last_event_ts = None","preventionTips":["Initialize all resettable attributes in `__init__` so reset never touches unset state.","Make `on_reset` idempotent and safe to call on a never-started strategy.","Run backtests in loops during development so reset bugs surface early.","Prefer tolerant clears (dict.pop, suppress, hasattr checks) over hard failures in reset."],"tags":["python","strategy","lifecycle","on-reset"],"backgroundTag":"python-callback-raised","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"}