nautechsystems/nautilus_trader · error

{field} {value} must be greater than zero and less than one

Error message

{field} {value} must be greater than zero and less than one

What it means

Polymarket binary-market prices are probabilities and must lie strictly between 0 and 1. validate_price_evidence rejects any price evidence that is zero, negative, one, or greater than one before it can become a domain Price.

Source

Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:293

            value >= Decimal::ZERO,
            "{field} {value} must be non-negative"
        );
    } else {
        anyhow::ensure!(value > Decimal::ZERO, "{field} {value} must be positive");
    }

    let quantity = Quantity::from_decimal_dp(value, precision).with_context(|| {
        format!("failed to represent {field} {value} with quantity precision {precision}")
    })?;
    anyhow::ensure!(
        quantity.as_decimal() == value,
        "{field} {value} is not exactly representable with quantity precision {precision}",
    );
    Ok(())
}

fn validate_price_evidence(value: Decimal, precision: u8, field: &str) -> anyhow::Result<()> {
    anyhow::ensure!(
        value > Decimal::ZERO && value < Decimal::ONE,
        "{field} {value} must be greater than zero and less than one",
    );
    let price = Price::from_decimal_dp(value, precision).with_context(|| {
        format!("failed to represent {field} {value} with price precision {precision}")
    })?;
    anyhow::ensure!(
        price.as_decimal() == value,
        "{field} {value} is not exactly representable with price precision {precision}",
    );
    Ok(())
}

fn validate_historical_price_evidence(value: Decimal, field: &str) -> anyhow::Result<Price> {
    anyhow::ensure!(
        value > Decimal::ZERO && value < Decimal::ONE,
        "{field} {value} must be greater than zero and less than one",
    );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check unit conventions: convert cent prices to decimals (divide by 100) if your code works in cents.
  2. Confirm the market has not resolved; 0/1 prices are normal post-resolution but invalid for active reconciliation.
  3. Skip zero-price rows (often placeholders for cancellations) before validation.
  4. Verify the price field being passed is actually a price, not size or another quantity.

Example fix

// before
validate_price_evidence(row.price, precision, "price")?;
// after
let price = if row.price > Decimal::ONE { row.price / Decimal::from(100) } else { row.price }; // cents -> probability
validate_price_evidence(price, precision, "price")?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_probability(p: Decimal) -> bool { p > Decimal::ZERO && p < Decimal::ONE }

Type guard

fn as_probability(v: Decimal) -> Option<Decimal> {
    is_valid_probability(v).then_some(v)
}

Try / catch

match validate_price_evidence(price, precision, "price") {
    Err(e) if e.to_string().contains("less than one") => { skip_row(row_id); Ok(()) }
    other => other,
}

Prevention

When it happens

Trigger: validate_order_row_values -> validate_price_evidence is called with a price Decimal <= 0 or >= 1 — e.g. a price of 0 on a cancelled row, 1.0 on a resolved market, or a raw-cents value like 55 instead of 0.55.

Common situations: Sending prices in cents (0–100) instead of probability decimals (0–1); prices captured after market resolution at 0 or 1; provider returning 0-price placeholder rows.

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