{"record":{"id":"77afae03dd17f2f9","repo":"nautechsystems/nautilus_trader","slug":"python-on-block-failed-e","errorCode":null,"errorMessage":"Python on_block failed: {e}","messagePattern":"Python on_block failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/python/actor.rs","lineNumber":1169,"sourceCode":"    fn on_instrument_close(&mut self, update: &InstrumentClose) -> anyhow::Result<()> {\n        self.dispatch_on_instrument_close(*update)\n            .map_err(|e| anyhow::anyhow!(\"Python on_instrument_close failed: {e}\"))\n    }\n\n    fn on_option_greeks(&mut self, greeks: &OptionGreeks) -> anyhow::Result<()> {\n        self.dispatch_on_option_greeks(*greeks)\n            .map_err(|e| anyhow::anyhow!(\"Python on_option_greeks failed: {e}\"))\n    }\n\n    fn on_option_chain(&mut self, slice: &OptionChainSlice) -> anyhow::Result<()> {\n        self.dispatch_on_option_chain(slice.clone())\n            .map_err(|e| anyhow::anyhow!(\"Python on_option_chain failed: {e}\"))\n    }\n\n    #[cfg(feature = \"defi\")]\n    fn on_block(&mut self, block: &Block) -> anyhow::Result<()> {\n        self.dispatch_on_block(block.clone())\n            .map_err(|e| anyhow::anyhow!(\"Python on_block failed: {e}\"))\n    }\n\n    #[cfg(feature = \"defi\")]\n    fn on_pool(&mut self, pool: &Pool) -> anyhow::Result<()> {\n        self.dispatch_on_pool(pool.clone())\n            .map_err(|e| anyhow::anyhow!(\"Python on_pool failed: {e}\"))\n    }\n\n    #[cfg(feature = \"defi\")]\n    fn on_pool_swap(&mut self, swap: &PoolSwap) -> anyhow::Result<()> {\n        self.dispatch_on_pool_swap(swap.clone())\n            .map_err(|e| anyhow::anyhow!(\"Python on_pool_swap failed: {e}\"))\n    }\n\n    #[cfg(feature = \"defi\")]\n    fn on_pool_liquidity_update(&mut self, update: &PoolLiquidityUpdate) -> anyhow::Result<()> {\n        self.dispatch_on_pool_liquidity_update(update.clone())\n            .map_err(|e| anyhow::anyhow!(\"Python on_pool_liquidity_update failed: {e}\"))","sourceCodeStart":1151,"sourceCodeEnd":1187,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/python/actor.rs#L1151-L1187","documentation":"This error wraps any Python exception raised inside the actor's `on_block` callback when a DeFi `Block` event is dispatched to the Python subclass (only compiled with the `defi` feature). The Rust `PyDataActor` clones the block, converts it via `into_py_any`, and calls the Python method via `call_method1`; a resulting `PyErr` becomes an anyhow error with this message. The exception originates in the user's Python override or the Rust-to-Python conversion.","triggerScenarios":"Any exception raised by the user's `on_block(self, block)` override — e.g. parsing block.number/block_hash with wrong assumptions, state keyed by a hash type that changed in conversion, or a raising Rust-to-Python conversion of Block.","commonSituations":"DeFi/on-chain strategies monitoring blocks whose handlers were written against an older Block binding; using string methods on a field that arrives as bytes (or vice versa) after conversion.","solutions":["Read the appended Python traceback after 'Python on_block failed:' to locate the raising line.","Confirm the Block field types in Python (str vs bytes for hashes) before string operations.","Enable/rebuild with the defi feature consistently so bindings match your Python stubs.","Add unit tests feeding synthetic Block objects to the handler."],"exampleFix":"// before\ndef on_block(self, block):\n    if block.hash.startswith(\"0x\"):\n        self.recent.append(block.hash)\n\n// after\ndef on_block(self, block):\n    h = block.hash.decode() if isinstance(block.hash, bytes) else block.hash\n    if h.startswith(\"0x\"):\n        self.recent.append(h)","handlingStrategy":"type-guard","validationCode":"h = block.hash\nif isinstance(h, bytes):\n    h = h.hex()\nif not h:\n    return","typeGuard":"def is_valid_block(block):\n    h = getattr(block, \"hash\", None)\n    return isinstance(h, (str, bytes)) and len(h) > 0","tryCatchPattern":"def on_block(self, block):\n    try:\n        self._monitor_block(block)\n    except Exception as e:\n        self.log.error(f\"on_block failed: {e}\", exc_info=True)","preventionTips":["Normalize hash fields (str vs bytes) at the handler entry point","Keep the defi feature enabled consistently across build and Python stubs","Test DeFi handlers with synthetic Block objects","Review Block bindings after nautilus_trader upgrades"],"tags":["python","rust-bridge","callback-exception","defi","actor"],"backgroundTag":"python-callback-failed","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"}