{"record":{"id":"7b73a4f3228aa9fd","repo":"nautechsystems/nautilus_trader","slug":"python-on-stop-failed-e-7b73a4","errorCode":null,"errorMessage":"Python on_stop failed: {e}","messagePattern":"Python on_stop failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/trading/src/python/algorithm.rs","lineNumber":553,"sourceCode":"            .dispatch_position_event(\"on_position_closed\", PositionEvent::PositionClosed(event));\n    }\n\n    fn on_position_event(&mut self, event: PositionEvent) {\n        let _ = self.dispatch_position_event(\"on_position_event\", event);\n    }\n}\n\nimpl DataActor for PyExecutionAlgorithm {\n    fn on_start(&mut self) -> anyhow::Result<()> {\n        ExecutionAlgorithm::on_start(self)?;\n        self.dispatch_no_args(\"on_start\")\n            .map_err(|e| anyhow::anyhow!(\"Python on_start failed: {e}\"))\n    }\n\n    fn on_stop(&mut self) -> anyhow::Result<()> {\n        ExecutionAlgorithm::on_stop(self)?;\n        self.dispatch_no_args(\"on_stop\")\n            .map_err(|e| anyhow::anyhow!(\"Python on_stop failed: {e}\"))\n    }\n\n    fn on_resume(&mut self) -> anyhow::Result<()> {\n        ExecutionAlgorithm::on_resume(self)?;\n        self.dispatch_no_args(\"on_resume\")\n            .map_err(|e| anyhow::anyhow!(\"Python on_resume failed: {e}\"))\n    }\n\n    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    }","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/trading/src/python/algorithm.rs#L535-L571","documentation":"The DataActor on_stop path first runs Rust ExecutionAlgorithm::on_stop, then dispatches Python `on_stop`; a Python exception is re-wrapped with this message. It means the Python component failed during orderly shutdown.","triggerScenarios":"Calling on_stop when the Python on_stop callback raises — e.g. errors while flushing/closing resources, or a bad no-arg dispatch.","commonSituations":"Closing an already-closed connection in on_stop; exception during final state persistence; callbacks that reference handlers cleared during shutdown.","solutions":["Read the chained `{e}` traceback and fix the Python on_stop implementation.","Make on_stop idempotent and defensive (guard already-closed/already-stopped resources).","Ensure state required by on_stop is not destroyed before stop is invoked.","Verify the Python class defines a zero-argument on_stop."],"exampleFix":"// before\ndef on_stop(self):\n    self.conn.close()  # raises if already closed\n\n// after\ndef on_stop(self):\n    if self.conn is not None and not self.conn.closed:\n        self.conn.close()","handlingStrategy":"try-catch","validationCode":"# Python: make stop idempotent before shutdown\nif getattr(self, \"stopped\", False): return","typeGuard":null,"tryCatchPattern":"if let Err(e) = actor.on_stop() {\n    log::error!(\"python on_stop failed: {e:#}\"); // still proceed with teardown\n}","preventionTips":["Write on_stop defensively: wrap each cleanup step so one failure doesn't abort the rest.","Track a stopped/disposed flag to make shutdown hooks idempotent.","Keep shutdown-time state (handlers, connections) alive until on_stop completes."],"tags":["rust","python","pyo3","lifecycle","on-stop"],"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"}