{"record":{"id":"daa299cf0b088535","repo":"nautechsystems/nautilus_trader","slug":"invalid-liquidityside-liquidity-side","errorCode":null,"errorMessage":"Invalid `LiquiditySide`: {liquidity_side}","messagePattern":"Invalid `LiquiditySide`: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/accounts/base.rs","lineNumber":403,"sourceCode":"    pub fn base_calculate_commission(\n        &self,\n        instrument: &InstrumentAny,\n        last_qty: Quantity,\n        last_px: Price,\n        liquidity_side: LiquiditySide,\n        use_quote_for_inverse: Option<bool>,\n    ) -> anyhow::Result<Money> {\n        anyhow::ensure!(\n            liquidity_side != LiquiditySide::NoLiquiditySide,\n            \"Invalid `LiquiditySide`: {liquidity_side}\"\n        );\n        let notional =\n            instrument.try_calculate_notional_value(last_qty, last_px, use_quote_for_inverse)?;\n        let rate = match liquidity_side {\n            LiquiditySide::Maker => instrument.maker_fee(),\n            LiquiditySide::Taker => instrument.taker_fee(),\n            LiquiditySide::NoLiquiditySide => {\n                anyhow::bail!(\"Invalid `LiquiditySide`: {liquidity_side}\")\n            }\n        };\n        let commission = notional\n            .as_decimal()\n            .checked_mul(rate)\n            .ok_or_else(|| anyhow::anyhow!(\"commission calculation overflow\"))?;\n\n        Ok(Money::from_decimal(commission, notional.currency)?)\n    }\n}\n\n/// Updates the locked balance for the given instrument and currency, then recalculates the\n/// account balance for that currency from all per-(instrument, currency) locks.\n///\n/// The reservation is recorded without a balance when the currency has no observed balance yet,\n/// so a later balance report derives from it.\n///\n/// # Errors","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/accounts/base.rs#L385-L421","documentation":"`base_calculate_commission` maps the trade's `LiquiditySide` to maker or taker fees. `LiquiditySide::NoLiquiditySide` carries no fee rate, so a commission cannot be computed and the method bails naming the liquidity side. Commission calculation requires the order to have been recorded as maker or taker.","triggerScenarios":"Calling `calculate_commission` on an account/instrument with an order event whose `liquidity_side` is `NoLiquiditySide` — e.g. passing an unfilled OrderInitialized/Submitted event, or constructing an OrderFilled without setting the liquidity side.","commonSituations":"Simulated fills in a backtest where the fill builder omitted liquidity_side, aggregating fees across an order's lifecycle including pre-fill events, or a venue adapter that doesn't populate liquidity side.","solutions":["Only call commission calculation on `OrderFilled` events where liquidity_side is Maker or Taker.","Set liquidity_side explicitly when constructing fills (from venue data or fill model in backtests).","Check the venue/data adapter populates the liquidity side field.","Skip/short-circuit NoLiquiditySide events in your fee aggregation loop before calling the API."],"exampleFix":"// before\nlet fee = account.calculate_commission(&instrument, &order.last_event(), qty, px)?;\n// after\nif order.last_event().liquidity_side() != LiquiditySide::NoLiquiditySide {\n    let fee = account.calculate_commission(&instrument, &order.last_event(), qty, px)?;\n}","handlingStrategy":"type-guard","validationCode":"if event.liquidity_side() == LiquiditySide::NoLiquiditySide {\n    // skip commission calculation; no fee determinable\n} else {\n    let fee = account.calculate_commission(&instrument, &event, last_qty, last_px)?;\n}","typeGuard":"fn has_fee_side(side: LiquiditySide) -> bool {\n    matches!(side, LiquiditySide::Maker | LiquiditySide::Taker)\n}","tryCatchPattern":"match account.calculate_commission(&instrument, &event, qty, px) {\n    Err(e) if e.to_string().contains(\"Invalid `LiquiditySide`\") => {\n        log::warn!(\"event has NoLiquiditySide; skipping fee\");\n    }\n    r => r?,\n}","preventionTips":["Only compute commissions on OrderFilled events with a maker/taker side.","Ensure fill models and venue adapters always populate liquidity_side.","Filter pre-fill order events out of fee aggregation loops."],"tags":["commission","liquidity-side","enum","fees"],"backgroundTag":"invalid-enum-value","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"}