nautechsystems/nautilus_trader · error

Python FeeModel.get_commission failed: {e}

Error message

Python FeeModel.get_commission failed: {e}

What it means

After the inner pyo3 call in the Python FeeModel wrapper fails, the outer `map_err` re-wraps whatever error occurred (including the `{e}` error from 3957) with the contextual message `Python FeeModel.get_commission failed: {e}`. It is the top-level context wrapper for failures of the Python-implemented `get_commission`.

Source

Thrown at crates/execution/src/python/fee.rs:195

        &self,
        order: &OrderAny,
        fill_quantity: Quantity,
        fill_px: Price,
        instrument: &InstrumentAny,
    ) -> anyhow::Result<Money> {
        Python::attach(|py| -> anyhow::Result<Money> {
            let order = order_any_to_pyobject(py, order.clone())?;
            let instrument = instrument_any_to_pyobject(py, instrument.clone())?;
            self.obj
                .bind(py)
                .call_method1(
                    "get_commission",
                    (order, fill_quantity, fill_px, instrument),
                )?
                .extract()
                .map_err(|e| anyhow::anyhow!("{e}"))
        })
        .map_err(|e| anyhow::anyhow!("Python FeeModel.get_commission failed: {e}"))
    }

    fn get_commission_with_context(
        &self,
        order: &OrderAny,
        fill_quantity: Quantity,
        fill_px: Price,
        instrument: &InstrumentAny,
        underlying_px: Option<Price>,
    ) -> anyhow::Result<Money> {
        Python::attach(|py| -> anyhow::Result<Money> {
            let obj = self.obj.bind(py);
            if !has_method_override_before_base(py, obj, "get_commission_with_context")? {
                let order = order_any_to_pyobject(py, order.clone())?;
                let instrument = instrument_any_to_pyobject(py, instrument.clone())?;
                return obj
                    .call_method1(
                        "get_commission",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the `{e}` portion for the root cause (usually the original Python exception text).
  2. Fix the Python fee model signature: `get_commission(self, order, fill_quantity, fill_px, instrument)` returning a Money value.
  3. Add try/except logging inside the Python model to capture and diagnose the failing input.

Example fix

try:
    fee = fee_model.get_commission(order, qty, px, instrument)
except Exception as e:
    logger.exception("fee model failed for %s", instrument.id)
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

assert callable(getattr(fee_model, 'get_commission', None)), "FeeModel must implement get_commission"

Try / catch

match fee_model.get_commission(&order, qty, px, &instrument) {
    Ok(fee) => fee,
    Err(e) => {
        // message is "Python FeeModel.get_commission failed: <cause>"
        log::error!("{e}"); fallback_flat_fee()
    }
}

Prevention

When it happens

Trigger: Any failure inside the wrapped Python `get_commission` call chain: Python exceptions, argument conversion failures, or result extraction errors when the Rust FFI calls the Python fee model.

Common situations: Custom Python fee models with incorrect signatures or return types; unconvertible Pythont/Rust object types; errors raised in user Python logic (division by zero, missing instrument attributes).

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/bfa627c502b57d88. Report an issue: GitHub.