nautechsystems/nautilus_trader · error · anyhow::Error

trade quantity must be positive

Error message

trade quantity must be positive

What it means

The Polymarket WebSocket adapter validates parsed trade sizes before constructing a domain Quantity. A trade whose size parses to zero or a negative decimal cannot represent a valid trade quantity, so the adapter aborts dispatch with this anyhow error. It guards against malformed or hostile exchange payloads (e.g. zero-size prints, auction placeholders) entering the trading kernel.

Source

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

    account_id: AccountId,
    liquidity_side: LiquiditySide,
    ts_event: UnixNanos,
    ts_init: UnixNanos,
) -> anyhow::Result<FillReport> {
    let venue_order_id = VenueOrderId::from(trade.taker_order_id.as_str());
    let trade_id = TradeId::from(trade.id.as_str());
    let order_side = determine_order_side(
        trade.trader_side,
        trade.side,
        trade.asset_id.as_str(),
        trade.asset_id.as_str(),
    );

    let size_precision = instrument.size_precision();
    let price_precision = instrument.price_precision();
    let size_dec = parse_decimal_exact(&trade.size)?;
    let price_dec = parse_decimal_exact(&trade.price)?;
    anyhow::ensure!(size_dec > Decimal::ZERO, "trade quantity must be positive");
    anyhow::ensure!(
        price_dec > Decimal::ZERO && price_dec < Decimal::ONE,
        "trade price must be in (0, 1)"
    );
    let last_qty = Quantity::from_decimal_dp(size_dec, size_precision)?;
    let last_px = Price::from_decimal_dp(price_dec, price_precision)?;

    let fee_rate = instrument_taker_fee(instrument);
    let commission_value = compute_commission(
        fee_rate,
        instrument_fee_exponent(instrument)?,
        size_dec,
        price_dec,
        liquidity_side,
    )?;
    let pusd = crate::execution::get_pusd_currency();

    Ok(FillReport {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the raw trade payload and check the venue's size field for zero/negative values
  2. Skip or drop the offending message in the dispatch handler rather than failing the stream if zero-size prints are expected
  3. Update the adapter if Polymarket changed its message schema (check newer nautilus versions)
  4. Report the payload to the venue or nautilus-trader maintainers if it is genuinely invalid

Example fix

// before: whole stream errors on a zero-size print
anyhow::ensure!(size_dec > Decimal::ZERO, "trade quantity must be positive");
// after: tolerate and skip zero-size prints
if size_dec <= Decimal::ZERO {
    log::debug!("skipping trade with non-positive size {}", trade.size);
    return Ok(None);
}
Defensive patterns

Strategy: validation

Validate before calling

let size_dec = parse_decimal_exact(&trade.size)?;
if size_dec <= Decimal::ZERO {
    log::warn!("skipping trade with non-positive size {}", trade.size);
    return Ok(None);
}

Type guard

fn is_positive_size(raw: &str) -> bool {
    parse_decimal_exact(raw).map(|d| d > Decimal::ZERO).unwrap_or(false)
}

Prevention

When it happens

Trigger: Processing a polymarket trade message whose `size` field parses via parse_decimal_exact to Decimal::ZERO or negative — e.g. a size of "0", "0.0000", or a malformed negative value from the venue.

Common situations: Polymarket venue sending zero-size fills during auction phases or market transitions; upstream API changes emitting placeholder sizes; corrupted/duplicate messages replayed from a snapshot.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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