nautechsystems/nautilus_trader · error

invalid probability: must not be 1.0 (inverse would be zero)

Error message

invalid probability: must not be 1.0 (inverse would be zero)

What it means

check_probability_invertible validates that a probability is not exactly 1.0 before an inverse operation. The inverse probability is computed as 1 - probability; when probability is 1.0 the inverse is zero, which cannot be used (e.g. zero odds/volume in a derived Bet). The library refuses up-front instead of producing a degenerate value downstream.

Source

Thrown at crates/model/src/data/bet.rs:706

///
/// # Errors
///
/// Returns an error if `probability` is zero.
pub fn check_probability_non_zero(probability: Decimal) -> anyhow::Result<()> {
    if probability.is_zero() {
        anyhow::bail!("invalid probability: must be non-zero")
    }
    Ok(())
}

/// Checks that `probability` is invertible (not equal to 1.0).
///
/// # Errors
///
/// Returns an error if `probability` is 1.0.
pub fn check_probability_invertible(probability: Decimal) -> anyhow::Result<()> {
    if probability == Decimal::ONE {
        anyhow::bail!("invalid probability: must not be 1.0 (inverse would be zero)")
    }
    Ok(())
}

/// Converts a probability and volume into a Bet.
///
/// For a BUY side, this creates a BACK bet; for SELL, a LAY bet.
///
/// # Errors
///
/// Returns an error if `probability` is zero or the conversion overflows.
pub fn probability_to_bet(
    probability: Decimal,
    volume: Decimal,
    side: OrderSide,
) -> anyhow::Result<Bet> {
    check_probability_non_zero(probability)?;
    let price = checked_div(Decimal::ONE, probability)?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a probability strictly less than 1.0; clamp values to just below 1 (e.g. Decimal::new(999999, 6)) if the source may report certainty.
  2. Check the input before calling: if probability == Decimal::ONE, handle it as a special case (skip the inverse or use the complementary odds directly).
  3. Verify the upstream data source; a 1.0 probability usually indicates a feed or unit-conversion bug (e.g. 100 instead of 1, or 100% not divided by 100).

Example fix

// before
let bet = inverse_probability_to_bet(Decimal::ONE, volume, side)?;
// after
anyhow::ensure!(probability < Decimal::ONE, "probability must be < 1.0");
let bet = inverse_probability_to_bet(probability, volume, side)?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust
use rust_decimal::Decimal;
fn is_invertible_probability(p: Decimal) -> bool { p < Decimal::ONE && p >= Decimal::ZERO }
// Python
# def is_invertible_probability(p): return 0 <= p < 1

Try / catch

// Rust
match inverse_probability_to_bet(p, volume, side) {
    Ok(bet) => bet,
    Err(e) if e.to_string().contains("must not be 1.0") => handle_certain_outcome(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling inverse_probability_to_bet(probability, volume, side) or any code path that calls check_probability_invertible with probability == Decimal::ONE (exactly 1.0, not merely close to 1).

Common situations: Betting/trading code computing lay-side bets from a back probability of certainty; a data feed reporting 100% implied probability; a user passing a settled/known-outcome probability of 1.0 into bet construction.

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