nautechsystems/nautilus_trader · error
Invalid `LiquiditySide`: {liquidity_side}
Error message
Invalid `LiquiditySide`: {liquidity_side} What it means
`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.
Source
Thrown at crates/model/src/accounts/base.rs:403
pub fn base_calculate_commission(
&self,
instrument: &InstrumentAny,
last_qty: Quantity,
last_px: Price,
liquidity_side: LiquiditySide,
use_quote_for_inverse: Option<bool>,
) -> anyhow::Result<Money> {
anyhow::ensure!(
liquidity_side != LiquiditySide::NoLiquiditySide,
"Invalid `LiquiditySide`: {liquidity_side}"
);
let notional =
instrument.try_calculate_notional_value(last_qty, last_px, use_quote_for_inverse)?;
let rate = match liquidity_side {
LiquiditySide::Maker => instrument.maker_fee(),
LiquiditySide::Taker => instrument.taker_fee(),
LiquiditySide::NoLiquiditySide => {
anyhow::bail!("Invalid `LiquiditySide`: {liquidity_side}")
}
};
let commission = notional
.as_decimal()
.checked_mul(rate)
.ok_or_else(|| anyhow::anyhow!("commission calculation overflow"))?;
Ok(Money::from_decimal(commission, notional.currency)?)
}
}
/// Updates the locked balance for the given instrument and currency, then recalculates the
/// account balance for that currency from all per-(instrument, currency) locks.
///
/// The reservation is recorded without a balance when the currency has no observed balance yet,
/// so a later balance report derives from it.
///
/// # ErrorsView on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
let fee = account.calculate_commission(&instrument, &order.last_event(), qty, px)?;
// after
if order.last_event().liquidity_side() != LiquiditySide::NoLiquiditySide {
let fee = account.calculate_commission(&instrument, &order.last_event(), qty, px)?;
} Defensive patterns
Strategy: type-guard
Validate before calling
if event.liquidity_side() == LiquiditySide::NoLiquiditySide {
// skip commission calculation; no fee determinable
} else {
let fee = account.calculate_commission(&instrument, &event, last_qty, last_px)?;
} Type guard
fn has_fee_side(side: LiquiditySide) -> bool {
matches!(side, LiquiditySide::Maker | LiquiditySide::Taker)
} Try / catch
match account.calculate_commission(&instrument, &event, qty, px) {
Err(e) if e.to_string().contains("Invalid `LiquiditySide`") => {
log::warn!("event has NoLiquiditySide; skipping fee");
}
r => r?,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- fee quantity must be non-negative
- failed to request AX whoami
- Invalid NodeState value
- Invalid `ConnectionMode` value: {value}
- AX whoami returned no accounts to resolve fees from
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/daa299cf0b088535.
Report an issue: GitHub.