{"record":{"id":"468997cfd7538092","repo":"nautechsystems/nautilus_trader","slug":"python-on-data-failed-e","errorCode":null,"errorMessage":"Python on_data failed: {e}","messagePattern":"Python on_data failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/python/actor.rs","lineNumber":1073,"sourceCode":"            .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        self.dispatch_on_time_event(event.clone())\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)\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","sourceCodeStart":1055,"sourceCodeEnd":1091,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/python/actor.rs#L1055-L1091","documentation":"Raised by the Rust `DataActor` bridge when the Python actor's `on_data(data)` handler raises an exception. The Rust side wraps the CustomData into a Python object (`Py::new`) and dispatches it via `dispatch_on_data`; a Python exception is rewrapped as this anyhow error. This fires for each custom data message delivered to a subscribed actor.","triggerScenarios":"Any exception in the Python `on_data` handler: unpacking the data payload into a wrong type, passing a non-serializable object between Rust and Python, or raising while processing a malformed message.","commonSituations":"Custom data subscriptions (external feeds, ML features) where on_data assumes a specific dataclass but receives a different payload type; attribute errors accessing fields absent from the data type; pyo3 conversion errors on Py::new for unsupported data types.","solutions":["Read the Python traceback in the error to locate the failing line in on_data.","Type-check the incoming data (isinstance) before accessing its fields, especially with multiple subscriptions.","Ensure the custom data type is properly registered/pyo3-compatible so Py::new conversion succeeds.","Guard processing logic in try/except and log malformed messages instead of raising."],"exampleFix":"// before (Python)\ndef on_data(self, data):\n    price = data.value\n\n// after\ndef on_data(self, data):\n    if isinstance(data, MyCustomData):\n        price = data.value\n    else:\n        self.log.warning(f\"unexpected data type: {type(data)}\")","handlingStrategy":"type-guard","validationCode":"def check_data(data, expected_type):\n    if not isinstance(data, expected_type):\n        raise TypeError(f'on_data expected {expected_type}, got {type(data)}')  # or log and return","typeGuard":"def is_expected_data(data, cls):\n    return isinstance(data, cls)","tryCatchPattern":"def on_data(self, data):\n    try:\n        ...  # processing\n    except Exception as e:\n        self.log.error(f\"on_data processing failed: {e}\")","preventionTips":["isinstance-check incoming data when subscribed to multiple data types.","Ensure custom data types are pyo3-convertible (registered) so the Rust->Python wrap succeeds.","Validate payload fields exist before accessing them.","Log and skip malformed messages instead of raising from on_data."],"tags":["python","data-handler","callback-exception","rust-bridge"],"backgroundTag":"python-callback-raised-exception","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"}