{"record":{"id":"a679cef7c726c795","repo":"nautechsystems/nautilus_trader","slug":"python-on-funding-rate-failed-e","errorCode":null,"errorMessage":"Python on_funding_rate failed: {e}","messagePattern":"Python on_funding_rate failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/python/actor.rs","lineNumber":1143,"sourceCode":"\n    fn on_book(&mut self, order_book: &OrderBook) -> anyhow::Result<()> {\n        self.dispatch_on_book(order_book)\n            .map_err(|e| anyhow::anyhow!(\"Python on_book failed: {e}\"))\n    }\n\n    fn on_mark_price(&mut self, mark_price: &MarkPriceUpdate) -> anyhow::Result<()> {\n        self.dispatch_on_mark_price(*mark_price)\n            .map_err(|e| anyhow::anyhow!(\"Python on_mark_price failed: {e}\"))\n    }\n\n    fn on_index_price(&mut self, index_price: &IndexPriceUpdate) -> anyhow::Result<()> {\n        self.dispatch_on_index_price(*index_price)\n            .map_err(|e| anyhow::anyhow!(\"Python on_index_price failed: {e}\"))\n    }\n\n    fn on_funding_rate(&mut self, funding_rate: &FundingRateUpdate) -> anyhow::Result<()> {\n        self.dispatch_on_funding_rate(*funding_rate)\n            .map_err(|e| anyhow::anyhow!(\"Python on_funding_rate failed: {e}\"))\n    }\n\n    fn on_instrument_status(&mut self, data: &InstrumentStatus) -> anyhow::Result<()> {\n        self.dispatch_on_instrument_status(*data)\n            .map_err(|e| anyhow::anyhow!(\"Python on_instrument_status failed: {e}\"))\n    }\n\n    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<()> {","sourceCodeStart":1125,"sourceCodeEnd":1161,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/python/actor.rs#L1125-L1161","documentation":"This error wraps any Python exception raised inside the actor's `on_funding_rate` callback when a `FundingRateUpdate` is dispatched to the Python subclass. The Rust `PyDataActor` calls the Python method via `call_method1` and converts the `PyErr` into an anyhow error with this message. The failure originates in the user's Python override or the Rust-to-Python data conversion.","triggerScenarios":"Any exception raised by the user's `on_funding_rate(self, funding_rate)` override — e.g. Decimal/float mixing when computing funding cost, missing dict entry for the instrument's funding history, or a helper that raises on the first funding-rate update after startup.","commonSituations":"Perpetual-futures strategies computing carry positions that hit a funding update before the position dict is initialized; version upgrades where FundingRateUpdate field names or types changed; funding rates arriving as Decimal where the handler assumed float.","solutions":["Read the appended Python traceback after 'Python on_funding_rate failed:' to find the raising line.","Initialize funding state in on_start so the first update never references uninitialized structures.","Check field names/types of FundingRateUpdate against your installed nautilus_trader version.","Use Decimal consistently for funding arithmetic to avoid type errors."],"exampleFix":"// before\ndef on_funding_rate(self, funding_rate):\n    cost = self.position * funding_rate.rate\n\n// after\ndef on_funding_rate(self, funding_rate):\n    if funding_rate.rate is None or self.position is None:\n        return\n    cost = Decimal(str(self.position)) * funding_rate.rate","handlingStrategy":"try-catch","validationCode":"from decimal import Decimal\nif funding_rate.rate is None:\n    return\nrate = Decimal(str(funding_rate.rate))","typeGuard":"def is_valid_funding_rate(update):\n    r = getattr(update, \"rate\", None)\n    return r is not None and isinstance(r, (int, float, Decimal))","tryCatchPattern":"def on_funding_rate(self, funding_rate):\n    try:\n        self._accrue_funding(funding_rate)\n    except Exception as e:\n        self.log.error(f\"on_funding_rate failed: {e}\", exc_info=True)","preventionTips":["Initialize funding state in on_start so the first update never hits missing structures","Use Decimal consistently for funding arithmetic","Check FundingRateUpdate fields against your version before upgrading","Handle unknown instrument IDs with a default entry instead of KeyError"],"tags":["python","rust-bridge","callback-exception","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"}