nautechsystems/nautilus_trader · error · anyhow::Error

invalid order quantity

Error message

invalid order quantity

What it means

build_ws_order_status_report() validates quantities before conversion to shares: the venue-reported original_size must parse to a decimal > 0, and size_matched (filled amount) must be >= 0 (an empty size_matched is treated as 0 for unfilled FOK cancellations). 'invalid order quantity' means original_size was zero/negative or size_matched was negative — the venue message cannot describe a real order, so the report is rejected.

Source

Thrown at crates/adapters/polymarket/src/websocket/dispatch.rs:1387

    let order_status =
        crate::execution::parse::resolve_order_status(status.status, order.event_type);
    let order_side = OrderSide::from(order.side);
    let time_in_force = TimeInForce::from(order_type);
    let size_precision = instrument.size_precision();
    let price_precision = instrument.price_precision();
    let price_dec = parse_decimal_exact(&order.price)?;
    anyhow::ensure!(
        price_dec > Decimal::ZERO && price_dec < Decimal::ONE,
        "order price must be in (0, 1)"
    );
    let quantity_dec = parse_decimal_exact(&order.original_size)?;
    // Unfilled FOK cancellations carry an empty size_matched in captured venue messages
    let filled_dec = if order.size_matched.is_empty() {
        Decimal::ZERO
    } else {
        parse_decimal_exact(&order.size_matched)?
    };
    anyhow::ensure!(
        quantity_dec > Decimal::ZERO && filled_dec >= Decimal::ZERO,
        "invalid order quantity"
    );
    let quantity = Quantity::from_decimal_dp(
        original_size_to_shares(quantity_dec, price_dec, order.side, order_type)?,
        size_precision,
    )?;
    let filled_qty = Quantity::from_decimal_dp(filled_dec, size_precision)?;
    let price = Price::from_decimal_dp(price_dec, price_precision)?;

    let mut report = OrderStatusReport::new(
        account_id,
        instrument.id(),
        None,
        venue_order_id,
        order_side.into(),
        OrderType::Limit,
        time_in_force,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the raw order payload to confirm what original_size/size_matched actually contained
  2. Update the adapter's field mapping if the venue schema changed so quantities land in the right fields
  3. Skip non-reportable message shapes upstream instead of building a report with degenerate quantities
  4. Fix test fixtures to carry a positive original_size (and non-negative size_matched)

Example fix

// before
anyhow::ensure!(
    quantity_dec > Decimal::ZERO && filled_dec >= Decimal::ZERO,
    "invalid order quantity"
);
// after — reject degenerate messages upstream before parsing
if order.original_size.is_empty() {
    return Ok(None); // no original size: nothing to report
}
anyhow::ensure!(
    quantity_dec > Decimal::ZERO && filled_dec >= Decimal::ZERO,
    "invalid order quantity"
);
Defensive patterns

Strategy: validation

Validate before calling

let qty: f64 = order.original_size.parse()?;
let filled: f64 = if order.size_matched.is_empty() { 0.0 } else { order.size_matched.parse()? };
if !(qty > 0.0 && filled >= 0.0) {
    return Ok(None); // degenerate venue message; skip instead of failing the report
}

Type guard

fn has_valid_venue_quantities(order: &WsOrder) -> bool {
    let qty = order.original_size.parse::<f64>().unwrap_or(0.0);
    let filled = order.size_matched.parse::<f64>().unwrap_or(0.0);
    qty > 0.0 && filled >= 0.0
}

Try / catch

match build_ws_order_status_report(&instrument, &order, ...) {
    Ok(report) => emit(report),
    Err(e) if e.to_string().contains("invalid order quantity") => {
        log::warn!("skipping order update with bad quantities size={:?} matched={:?}: {e:#}",
            order.original_size, order.size_matched);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: An order-update with original_size "0" or empty-but-non-matching values, a negative size_matched from a malformed or schema-changed message, or a fixture/test message missing quantity fields.

Common situations: Polymarket API message-shape changes shifting quantity fields; partially-filled cancel messages with unexpected matched sizes; corrupted feed data; hand-written test fixtures with zero sizes.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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