{"record":{"id":"43c47d77aafdcdac","repo":"nautechsystems/nautilus_trader","slug":"python-on-pool-failed-e","errorCode":null,"errorMessage":"Python on_pool failed: {e}","messagePattern":"Python on_pool failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/python/actor.rs","lineNumber":1175,"sourceCode":"        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}\"))\n    }\n\n    #[cfg(feature = \"defi\")]\n    fn on_pool_fee_collect(&mut self, collect: &PoolFeeCollect) -> anyhow::Result<()> {\n        self.dispatch_on_pool_fee_collect(collect.clone())\n            .map_err(|e| anyhow::anyhow!(\"Python on_pool_fee_collect failed: {e}\"))","sourceCodeStart":1157,"sourceCodeEnd":1193,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/python/actor.rs#L1157-L1193","documentation":"This error wraps any Python exception raised inside the actor's `on_pool` callback when a DeFi `Pool` update is dispatched to the Python subclass (only compiled with the `defi` feature). The Rust `PyDataActor` clones the pool, converts it via `into_py_any`, and calls the Python method via `call_method1`; a resulting `PyErr` is converted to an anyhow error with this message. The underlying exception is raised in the user's Python override or during conversion.","triggerScenarios":"Any exception raised by the user's `on_pool(self, pool)` override — e.g. Decimal division by pool liquidity of zero, dict lookups on an unseen pool address/instrument_id, or a raising Rust-to-Python conversion of Pool.","commonSituations":"AMM/LP strategies tracking pools that encounter a freshly created or drained pool with zero liquidity; handlers written for an older Pool binding before an upgrade; pool identifiers changing format between chain deployments.","solutions":["Read the appended Python traceback after 'Python on_pool failed:' to locate the raising line.","Guard against zero/None liquidity and price fields before division or comparison.","Register the pool instrument before processing its updates so lookups succeed.","Verify Pool field names/types against the installed nautilus_trader version."],"exampleFix":"// before\ndef on_pool(self, pool):\n    price = pool.token0_reserve / pool.token1_reserve\n\n// after\ndef on_pool(self, pool):\n    if not pool.token1_reserve:\n        return\n    price = pool.token0_reserve / pool.token1_reserve","handlingStrategy":"validation","validationCode":"r0, r1 = pool.token0_reserve, pool.token1_reserve\nif not r0 or not r1:\n    return  # zero liquidity or uninitialized pool","typeGuard":"def is_tradeable_pool(pool):\n    r0 = getattr(pool, \"token0_reserve\", 0)\n    r1 = getattr(pool, \"token1_reserve\", 0)\n    return r0 and r1 and r0 > 0 and r1 > 0","tryCatchPattern":"def on_pool(self, pool):\n    try:\n        self._track_pool(pool)\n    except Exception as e:\n        self.log.error(f\"on_pool failed: {e}\", exc_info=True)","preventionTips":["Guard against zero/None reserves before computing pool price","Register pool instruments before processing their updates","Use .get() defaults for per-pool state to avoid KeyError","Test handlers against freshly created and drained pools"],"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-14T00:17:10.932Z"}