nautechsystems/nautilus_trader · error
invalid probability: must be non-zero
Error message
invalid probability: must be non-zero
What it means
check_probability_non_zero rejects a probability of exactly zero because converting probability to odds requires dividing by it (odds = 1/probability), which is undefined for zero. The library exposes it as a public checked helper.
Source
Thrown at crates/model/src/data/bet.rs:694
/// Calculates the combined profit and loss for a slice of bets.
///
/// # Errors
///
/// Returns an error if a payoff or the running total overflows.
pub fn calc_bets_pnl_checked(bets: &[Bet]) -> anyhow::Result<Decimal> {
bets.iter().try_fold(Decimal::ZERO, |acc, bet| {
checked_add(acc, bet.outcome_win_payoff_checked()?)
})
}
/// Checks that `probability` is non-zero.
///
/// # 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.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Validate probability > 0 (or > 1) before calling probability_to_bet
- Skip conversion for zero-probability outcomes at the caller level
- Fix upstream normalization so probabilities are never zero
Example fix
// before let bet = probability_to_bet(Decimal::ZERO, side)?; // bails // after let p = Decimal::new(25, 2); // 0.25 anyhow::ensure!(!p.is_zero(), "skip zero-probability outcome"); let bet = probability_to_bet(p, side)?;
Defensive patterns
Strategy: validation
Validate before calling
if probability.is_zero() { return Ok(None); } // or skip the outcome
let bet = probability_to_bet(probability, side)?; Type guard
fn is_usable_probability(p: Decimal) -> bool { !p.is_zero() } Try / catch
match probability_to_bet(probability, side) {
Err(e) if e.to_string().contains("must be non-zero") => { /* skip zero-probability outcome */ }
other => other?,
} Prevention
- Filter zero-probability outcomes before conversion
- Check normalization code so probabilities sum to 1 with no zeros from empty weights
- Call check_probability_non_zero early in input parsing
When it happens
Trigger: Calling check_probability_non_zero (directly or via probability_to_bet) with probability == Decimal::ZERO.
Common situations: Probabilities parsed from empty/placeholder data defaulting to 0; normalization bugs where all weights are zero leading to a zero probability; users mistaking zero for 'impossible event, skip' when they should skip the conversion themselves.
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
- Liability-based betting is only applicable for Lay side.
- invalid OrderSide: must be Buy or Sell, was {side}
- {e}
- {e}
- {FAILED}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b2a4130612e20336.
Report an issue: GitHub.