nautechsystems/nautilus_trader · error · anyhow::Error

trade price must be in (0, 1)

Error message

trade price must be in (0, 1)

What it means

Polymarket markets are probabilistic, so all trade prices must be strictly between 0 and 1. The adapter enforces this invariant before constructing a domain Price, rejecting any payload with a price outside the open unit interval.

Source

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

    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 {
        account_id,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the raw payload price — if it is quoted in cents (0–100), convert to probability by dividing by 100 before dispatch
  2. Decide whether settlement prices of exactly 0 or 1 are legitimate for your market and relax the bound accordingly
  3. Check for Polymarket schema changes and update the adapter
  4. Filter the message and continue if out-of-range prints are expected at market resolution

Example fix

// before: strict open-interval check rejects settlement prints
anyhow::ensure!(
    price_dec > Decimal::ONE.zero() && price_dec < Decimal::ONE,
    "trade price must be in (0, 1)"
);
// after: accept resolved-market extremes
anyhow::ensure!(
    price_dec >= Decimal::ZERO && price_dec <= Decimal::ONE,
    "trade price must be in [0, 1]"
);
Defensive patterns

Strategy: validation

Validate before calling

let price_dec = parse_decimal_exact(&trade.price)?;
if price_dec <= Decimal::ZERO || price_dec >= Decimal::ONE {
    log::warn!("skipping trade with out-of-range price {}", trade.price);
    return Ok(None);
}

Type guard

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

Prevention

When it happens

Trigger: Processing a polymarket trade message whose `price` field parses to <= 0 or >= 1 — e.g. "1.0", "0", "1.5", or a price accidentally quoted in cents (e.g. "54" instead of "0.54").

Common situations: A venue feed switching to a different price convention (cents vs probability); settlement trades at exactly 1.0 or 0.0; malformed messages during resolution/market close events.

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/6e11b8a4fdd7c919. Report an issue: GitHub.