nautechsystems/nautilus_trader · error

quantity was undefined

Error message

quantity was undefined

What it means

wallet_money_from_quantity converts a Quantity into Money for wallet balance updates. It first asserts the quantity is defined (raw != u64::MAX sentinel, i.e. not 'undefined'); an undefined Quantity cannot represent a monetary amount, so it errors via anyhow::ensure!.

Source

Thrown at crates/portfolio/src/manager.rs:1415

                instrument.id().venue,
                source_currency,
                base_curr,
                if side == OrderSide::Buy {
                    PriceType::Bid
                } else {
                    PriceType::Ask
                },
            ),
        }
    }
}

#[allow(
    clippy::useless_conversion,
    reason = "the raw width differs when high-precision is disabled"
)]
fn wallet_money_from_quantity(quantity: Quantity, currency: Currency) -> anyhow::Result<Money> {
    anyhow::ensure!(!quantity.is_undefined(), "quantity was undefined");
    Quantity::from_raw_checked(quantity.raw, quantity.precision)?;
    check_fixed_raw_u128(u128::from(quantity.raw), quantity.precision)?;

    let source_precision = quantity.precision.max(FIXED_PRECISION);
    let target_precision = currency.precision.max(FIXED_PRECISION);
    let raw = i128::try_from(u128::from(quantity.raw))
        .map_err(|_| anyhow::anyhow!("quantity for {currency} exceeds signed raw bounds"))?;
    let raw = match source_precision.cmp(&target_precision) {
        Ordering::Less => {
            let scale = 10_i128.pow(u32::from(target_precision - source_precision));
            raw.checked_mul(scale).ok_or_else(|| {
                anyhow::anyhow!("quantity for {currency} overflowed while increasing raw scale")
            })?
        }
        Ordering::Greater => {
            let scale = 10_i128.pow(u32::from(source_precision - target_precision));
            anyhow::ensure!(
                raw % scale == 0,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the Quantity is set to a real value before updating locked balances
  2. Validate event/adapter data so undefined quantities never reach the portfolio manager
  3. Use Quantity::new_checked to construct quantities so invalid values fail early
  4. Skip or log-and-drop balance updates carrying undefined quantities

Example fix

// before
manager.update_balance_locked_wallet(&instrument.id(), asset, quantity)?;
// after
if quantity.is_undefined() {
    log::warn!("skipping locked-balance update: quantity undefined for {asset}");
} else {
    manager.update_balance_locked_wallet(&instrument.id(), asset, quantity)?;
}
Defensive patterns

Strategy: type-guard

Validate before calling

if quantity.is_undefined() {
    log::warn!("skipping wallet lock update: undefined quantity");
    return Ok(());
}

Type guard

fn is_defined(q: &Quantity) -> bool { !q.is_undefined() }

Try / catch

match manager.update_balance_locked_wallet(&instrument_id, currency, quantity) {
    Ok(_) => {}
    Err(e) if e.to_string().contains("quantity was undefined") => {
        log::warn!("undefined quantity for {currency}; skipping lock update");
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: update_balance_locked_wallet receiving a balance/locked amount whose Quantity was constructed with the UNDEFINED raw sentinel (Quantity::new_checked on NaN/None paths, or a default-uninitialized Quantity).

Common situations: Strategies that lock balances before any fill sets a quantity; adapters returning placeholder quantities; deserializing events with missing quantity fields; uninitialized struct fields defaulting to undefined.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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