{"record":{"id":"efc96ce9fd677b40","repo":"nautechsystems/nautilus_trader","slug":"invalid-name-must-be-non-zero","errorCode":null,"errorMessage":"invalid {name}: must be non-zero","messagePattern":"invalid (.+?): must be non-zero","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bet.rs","lineNumber":759,"sourceCode":"    probability: Decimal,\n    volume: Decimal,\n    side: OrderSide,\n) -> anyhow::Result<Bet> {\n    check_probability_invertible(probability)?;\n    let inverse_probability = checked_sub(Decimal::ONE, probability)?;\n    probability_to_bet(inverse_probability, volume, side.opposite())\n}\n\nfn check_odds_gt_one(price: Decimal) -> anyhow::Result<()> {\n    if price <= Decimal::ONE {\n        anyhow::bail!(\"Price must be greater than 1.0 for lay liability calculation, was {price}\");\n    }\n    Ok(())\n}\n\nfn check_nonzero_denominator(value: Decimal, name: &str) -> anyhow::Result<()> {\n    if value.is_zero() {\n        anyhow::bail!(\"invalid {name}: must be non-zero\")\n    }\n    Ok(())\n}\n\nfn checked_add(lhs: Decimal, rhs: Decimal) -> anyhow::Result<Decimal> {\n    lhs.checked_add(rhs)\n        .ok_or_else(|| anyhow::anyhow!(\"Decimal overflow adding {lhs} and {rhs}\"))\n}\n\nfn checked_sub(lhs: Decimal, rhs: Decimal) -> anyhow::Result<Decimal> {\n    lhs.checked_sub(rhs)\n        .ok_or_else(|| anyhow::anyhow!(\"Decimal overflow subtracting {rhs} from {lhs}\"))\n}\n\nfn checked_mul(lhs: Decimal, rhs: Decimal) -> anyhow::Result<Decimal> {\n    lhs.checked_mul(rhs)\n        .ok_or_else(|| anyhow::anyhow!(\"Decimal overflow multiplying {lhs} by {rhs}\"))\n}","sourceCodeStart":741,"sourceCodeEnd":777,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/bet.rs#L741-L777","documentation":"check_nonzero_denominator is a guard against division by zero in Bet arithmetic. It accepts a Decimal and its field name, and bails if the value is zero, so callers like as_bet_checked, decreased_state, flattening_bet_checked, and checked_div fail fast with a message naming the offending quantity instead of panicking or producing NaN/infinity.","triggerScenarios":"Any bet operation that divides by a user-supplied or computed denominator (volume, price, size) when that value is exactly Decimal::ZERO — e.g. checked_div with rhs = 0, as_bet_checked with zero size, decreased_state / flattening_bet_checked after the bet was fully filled or cancelled to zero volume.","commonSituations":"Operating on a bet whose remaining volume reached zero; passing an unfilled/zero Quantity placeholder; a data feed supplying 0 size for an unmatched order.","solutions":["Check the denominator with .is_zero() before the operation and handle the zero case explicitly (skip, treat result as zero, or error).","Filter out zero-volume bets/orders before running bet state transitions or divisions.","Verify the upstream data: a zero denominator often means the position is already flat and the operation is unnecessary."],"exampleFix":"// before\nlet ratio = checked_div(pnl, remaining_volume)?;\n// after\nif remaining_volume.is_zero() {\n    return Ok(Decimal::ZERO); // nothing remains to normalize against\n}\nlet ratio = checked_div(pnl, remaining_volume)?;","handlingStrategy":"validation","validationCode":"// Rust\nuse rust_decimal::Decimal;\nfn safe_div(n: Decimal, d: Decimal) -> Option<Decimal> { if d.is_zero() { None } else { Some(n / d) } }","typeGuard":null,"tryCatchPattern":"// Rust\nmatch as_bet_checked(volume) {\n    Ok(bet) => bet,\n    Err(e) if e.to_string().contains(\"must be non-zero\") => handle_flat_position(),\n    Err(e) => return Err(e),\n}","preventionTips":["Always test .is_zero() on denominators before division.","Skip state transitions on fully filled / zero-remaining-volume bets.","Validate that feed sizes are positive before constructing bets."],"tags":["decimal","division-by-zero","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}