{"record":{"id":"36a601349fb8aa67","repo":"nautechsystems/nautilus_trader","slug":"e-36a601","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/python/fee.rs","lineNumber":193,"sourceCode":"impl FeeModel for PythonFeeModel {\n    fn get_commission(\n        &self,\n        order: &OrderAny,\n        fill_quantity: Quantity,\n        fill_px: Price,\n        instrument: &InstrumentAny,\n    ) -> anyhow::Result<Money> {\n        Python::attach(|py| -> anyhow::Result<Money> {\n            let order = order_any_to_pyobject(py, order.clone())?;\n            let instrument = instrument_any_to_pyobject(py, instrument.clone())?;\n            self.obj\n                .bind(py)\n                .call_method1(\n                    \"get_commission\",\n                    (order, fill_quantity, fill_px, instrument),\n                )?\n                .extract()\n                .map_err(|e| anyhow::anyhow!(\"{e}\"))\n        })\n        .map_err(|e| anyhow::anyhow!(\"Python FeeModel.get_commission failed: {e}\"))\n    }\n\n    fn get_commission_with_context(\n        &self,\n        order: &OrderAny,\n        fill_quantity: Quantity,\n        fill_px: Price,\n        instrument: &InstrumentAny,\n        underlying_px: Option<Price>,\n    ) -> anyhow::Result<Money> {\n        Python::attach(|py| -> anyhow::Result<Money> {\n            let obj = self.obj.bind(py);\n            if !has_method_override_before_base(py, obj, \"get_commission_with_context\")? {\n                let order = order_any_to_pyobject(py, order.clone())?;\n                let instrument = instrument_any_to_pyobject(py, instrument.clone())?;\n                return obj","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/python/fee.rs#L175-L211","documentation":"The Python fee model wrapper calls the user-provided Python object's `get_commission` via pyo3 and converts the result. The inner `map_err(|e| anyhow!(\"{e}\"))` surfaces any pyo3 conversion/call error (Python exception or failed result extraction) with just the exception's text as this error message.","triggerScenarios":"Calling `get_commission` on a Python FeeModel whose `get_commission` raises a Python exception, returns an object not extractable as the expected type, or accepts different arguments than `(order, fill_quantity, fill_px, instrument)`.","commonSituations":"Custom Python fee model with a wrong method signature; returning `None` or a non-Money value; exception inside user Python code (e.g. KeyError on instrument dict); passing objects not convertible between Rust/Python (version/type mismatch of bindings).","solutions":["Read the wrapped `{e}` text — it is the original Python exception — and fix the Python fee model accordingly.","Ensure the Python `get_commission(self, order, fill_quantity, fill_px, instrument)` signature matches exactly and returns a Money-compatible value.","Test the Python model standalone with representative order/instrument objects to reproduce the exception."],"exampleFix":"# before: wrong signature/return\ndef get_commission(self, order, qty, px):\n    return None\n# after\ndef get_commission(self, order, fill_quantity, fill_px, instrument):\n    return Money(fill_quantity * fill_px * self.rate, instrument.quote_currency)","handlingStrategy":"try-catch","validationCode":"import inspect\nsig = inspect.signature(fee_model.get_commission)\nassert list(sig.parameters) == ['self', 'order', 'fill_quantity', 'fill_px', 'instrument']","typeGuard":"def is_valid_fee_model(obj) -> bool:\n    return callable(getattr(obj, 'get_commission', None)) and \\\n           len(inspect.signature(obj.get_commission).parameters) == 4","tryCatchPattern":"try:\n    fee = fee_model.get_commission(order, qty, px, instrument)\nexcept Exception as e:\n    logger.exception(\"FeeModel.get_commission failed: %s\", e)\n    fee = None","preventionTips":["Match the exact Python method signature (order, fill_quantity, fill_px, instrument).","Return a Money-compatible value, never None.","Unit-test Python fee models standalone before wiring into the trading node.","Log the full exception inside the Python model for root-cause visibility."],"tags":["python","pyo3","fee-model","binding","rust"],"backgroundTag":"api-error-response","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"}