nautechsystems/nautilus_trader · error · anyhow::Error

order price must be in (0, 1)

Error message

order price must be in (0, 1)

What it means

build_ws_order_status_report() converts a venue order-update message into an OrderStatusReport and enforces that the venue-reported order price, parsed as an exact decimal, lies strictly between 0 and 1 — Polymarket prices are probabilities in the open interval (0, 1). A price of 0, 1, or outside that range means the venue message is malformed, uses a placeholder price (e.g. for market orders), or a parsing assumption broke, so the report is rejected rather than propagated with bogus data.

Solutions

  1. Log the full raw order message to see what venue actually sent for price
  2. Skip/ignore reports for message types that legitimately carry no price (e.g. pure cancels) instead of building a report
  3. Update the parsing/mapping in the adapter if the venue schema changed and price moved fields
  4. If your own code produces the message (tests/fixtures), supply a valid price strictly between 0 and 1

Example fix

// before
anyhow::ensure!(
    price_dec > Decimal::ZERO && price_dec < Decimal::ONE,
    "order price must be in (0, 1)"
);
// after — treat priceless message shapes as non-reportable upstream
if order.price.is_empty() || order.price == "0" {
    return Ok(None); // venue sent a placeholder price; no report to emit
}
anyhow::ensure!(
    price_dec > Decimal::ZERO && price_dec < Decimal::ONE,
    "order price must be in (0, 1)"
);
Defensive patterns

Strategy: validation

Validate before calling

// validate before accepting a venue order update into your book/state
let p: f64 = order.price.parse()?;
if !(p > 0.0 && p < 1.0) {
    // skip or quarantine the message; do not build a report
    return Ok(None);
}

Type guard

fn has_valid_venue_price(order: &WsOrder) -> bool {
    order.price.parse::<f64>().map(|p| p > 0.0 && p < 1.0).unwrap_or(false)
}

Try / catch

match build_ws_order_status_report(&instrument, &order, ...) {
    Ok(report) => emit(report),
    Err(e) if e.to_string().contains("order price must be in (0, 1)") => {
        log::warn!("skipping order update with invalid venue price {:?}: {e:#}", order.price);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A Polymarket WebSocket order-update carrying price "0" or "1" (e.g. zero-price placeholder on certain market-order/FOK records), an unparseable or shifted field mapped into order.price, or a venue schema change that moves the real price elsewhere.

Common situations: Market/FOK orders whose captured message has no meaningful limit price; new venue message fields after an API update; asset-level data corruption on the feed; tests feeding edge-case fixtures with price 0/1.

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/27aac0ec69ddee51. Report an issue: GitHub.

Appendix: source

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

fn build_ws_order_status_report(
    order: &PolymarketUserOrder,
    status: &PolymarketUserOrderStatus,
    order_type: PolymarketOrderType,
    instrument: &InstrumentAny,
    account_id: AccountId,
    ts_event: UnixNanos,
    ts_init: UnixNanos,
) -> anyhow::Result<OrderStatusReport> {
    let venue_order_id = VenueOrderId::from(order.id.as_str());
    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,
    )?;

View on GitHub (pinned to 18893faf8b)