{"record":{"id":"5ad4fe3ed579cc7f","repo":"nautechsystems/nautilus_trader","slug":"python-on-socket-state-failed-e-5ad4fe","errorCode":null,"errorMessage":"Python on_socket_state failed: {e}","messagePattern":"Python on_socket_state failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/trading/src/python/algorithm.rs","lineNumber":601,"sourceCode":"    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\n    fn on_socket_state(&mut self, event: &SocketStateChanged) -> anyhow::Result<()> {\n        self.dispatch_on_socket_state(event)\n            .map_err(|e| anyhow::anyhow!(\"Python on_socket_state failed: {e}\"))\n    }\n}\n\n#[pyo3::pymethods]\n#[pyo3_stub_gen::derive::gen_stub_pymethods]\n#[allow(\n    clippy::large_types_passed_by_value,\n    reason = \"PyO3 callbacks accept Python-owned event values\"\n)]\n#[expect(\n    clippy::unused_self,\n    reason = \"default PyO3 callbacks must remain instance methods\"\n)]\nimpl PyExecutionAlgorithm {\n    /// Creates a new [`PyExecutionAlgorithm`] instance.\n    #[new]\n    #[pyo3(signature = (config=None))]\n    fn py_new(config: Option<Py<PyAny>>) -> Self {","sourceCodeStart":583,"sourceCodeEnd":619,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/trading/src/python/algorithm.rs#L583-L619","documentation":"Raised by the Rust `ExecutionAlgorithm` wrapper when the Python callback `on_socket_state` throws. `SocketStateChanged` events (connection state transitions) are dispatched to the Python subclass via `dispatch_on_socket_state`; any `PyErr` raised in the user's handler is wrapped as `anyhow!(\"Python on_socket_state failed: {e}\")`.","triggerScenarios":"A connection's `SocketStateChanged` event (e.g. CONNECTED/DISCONNECTED) is delivered to a registered algorithm whose Python subclass overrides `on_socket_state` and raises — e.g. reconnection logic that touches dead resources, or referencing wrong event fields.","commonSituations":"Custom reconnection/bookkeeping hooks that call clients or cancel orders while the socket is down; handlers written against an older event API; exceptions thrown while the adapter is shutting down.","solutions":["Read the chained Python traceback in the message to locate the failure inside your `on_socket_state` override","Make the handler state-safe: do not assume clients/orders are usable during DISCONNECTED transitions","Wrap the body in try/except and log failures instead of propagating","Match the signature `def on_socket_state(self, event) -> None:` and read only documented `SocketStateChanged` fields","Remove the override if you don't need socket-state visibility"],"exampleFix":"# before\ndef on_socket_state(self, event):\n    self.client.resubscribe_all()  # raises while socket is disconnected\n\n# after\ndef on_socket_state(self, event):\n    try:\n        if event.is_connected:\n            self.client.resubscribe_all()\n    except Exception as e:\n        self.log.error(f\"socket-state handler failed: {e}\")","handlingStrategy":"try-catch","validationCode":"sig = inspect.signature(MyAlgo.on_socket_state)\nassert list(sig.parameters) == ['self', 'event']","typeGuard":"def is_socket_state_event(ev):\n    return type(ev).__name__ == 'SocketStateChanged'","tryCatchPattern":"try:\n    algo.on_socket_state(event)\nexcept Exception as e:\n    log.error(f\"on_socket_state handler failed: {e}\")  # resubscribe/recovery errors stay non-fatal","preventionTips":["Guard reconnection logic: assume resources are unavailable during DISCONNECTED transitions","Keep the handler idempotent so repeated socket transitions don't accumulate failures","Wrap the body in try/except and log; socket events can arrive during shutdown","Verify event field names against the current `SocketStateChanged` API after upgrades"],"tags":["python","callback","socket","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-14T05:17:10.506Z"}