nautechsystems/nautilus_trader · error
Python on_socket_state failed: {e}
Error message
Python on_socket_state failed: {e} What it means
Wraps any failure raised when the Rust core dispatches a `SocketStateChanged` event into the Python actor's `on_socket_state` handler. The error indicates the Python handler raised (or dispatch into Python failed); Rust re-raises with the 'Python on_socket_state failed' prefix.
Source
Thrown at crates/common/src/python/actor.rs:1089
let py_data: Py<PyAny> = Py::new(py, data.clone())?.into_any();
self.dispatch_on_data(py_data)
.map_err(|e| anyhow::anyhow!("Python on_data failed: {e}"))
})
}
fn on_signal(&mut self, signal: &Signal) -> anyhow::Result<()> {
self.dispatch_on_signal(signal)
.map_err(|e| anyhow::anyhow!("Python on_signal failed: {e}"))
}
fn on_queue_state(&mut self, event: &QueueStateChanged) -> anyhow::Result<()> {
self.dispatch_on_queue_state(event)
.map_err(|e| anyhow::anyhow!("Python on_queue_state failed: {e}"))
}
fn on_socket_state(&mut self, event: &SocketStateChanged) -> anyhow::Result<()> {
self.dispatch_on_socket_state(event)
.map_err(|e| anyhow::anyhow!("Python on_socket_state failed: {e}"))
}
fn on_instrument(&mut self, instrument: &InstrumentAny) -> anyhow::Result<()> {
Python::attach(|py| {
let py_instrument = instrument_any_to_pyobject(py, instrument.clone())
.map_err(|e| anyhow::anyhow!("Failed to convert InstrumentAny to Python: {e}"))?;
self.dispatch_on_instrument(py_instrument)
.map_err(|e| anyhow::anyhow!("Python on_instrument failed: {e}"))
})
}
fn on_quote(&mut self, quote: &QuoteTick) -> anyhow::Result<()> {
self.dispatch_on_quote(*quote)
.map_err(|e| anyhow::anyhow!("Python on_quote failed: {e}"))
}
fn on_trade(&mut self, tick: &TradeTick) -> anyhow::Result<()> {
self.dispatch_on_trade(*tick)View on GitHub (pinned to 18893faf8b)
Solutions
- Read the chained `{e}` message for the underlying Python traceback and fix the handler
- Verify the override signature `on_socket_state(self, event)` with a SocketStateChanged argument
- Handle all socket-state enum cases (Connected, Disconnected, etc.) without assuming prior state
- Wrap risky reconnect logic in try/except and log instead of raising
Example fix
// before
def on_socket_state(self, event):
self.client.close() # AttributeError when never connected
// after
def on_socket_state(self, event):
if self.client is not None:
self.client.close() Defensive patterns
Strategy: try-catch
Validate before calling
def _check_on_socket_state(self, event):
try:
self.on_socket_state(event)
except Exception as e:
self.log.error(f'on_socket_state failed: {e!r}') Try / catch
try:
self.dispatch_on_socket_state(event)
except Exception as e:
self.log.error(f'Python on_socket_state failed: {e}', exc_info=True) Prevention
- Handle Disconnected state when resources may not exist
- Never assume connection order in on_socket_state
- Test reconnect/disconnect paths explicitly
When it happens
Trigger: A socket state change event is delivered to a Python actor overriding `on_socket_state`, and the Python method raises an exception or cannot be dispatched (e.g. not callable).
Common situations: Connection/reconnect logic in `on_socket_state` that touches sockets or clients not yet created, wrong handler arity, or exceptions raised while reacting to Disconnected/Connected transitions.
Related errors
- Python on_order failed: {e}
- Python on_order_list failed: {e}
- Python on_signal failed: {e}
- Python on_queue_state failed: {e}
- Python on_instrument failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6e1991c2410706cf.
Report an issue: GitHub.