{"record":{"id":"b70cc8a91d5b58d6","repo":"nautechsystems/nautilus_trader","slug":"invalid-orderside-must-be-buy-or-sell-was-side","errorCode":null,"errorMessage":"invalid OrderSide: must be Buy or Sell, was {side}","messagePattern":"invalid OrderSide: must be Buy or Sell, was (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bet.rs","lineNumber":786,"sourceCode":"\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\n/// Converts [`OrderSide`] into a specified side for betting conversions.\n///\n/// # Errors\n///\n/// Returns an error if `side` is [`OrderSide::NoOrderSide`].\npub fn specified_order_side(side: OrderSide) -> anyhow::Result<OrderSideSpecified> {\n    match side {\n        OrderSide::Buy => Ok(OrderSideSpecified::Buy),\n        OrderSide::Sell => Ok(OrderSideSpecified::Sell),\n        OrderSide::NoOrderSide => {\n            anyhow::bail!(\"invalid OrderSide: must be Buy or Sell, was {side}\")\n        }\n    }\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":768,"sourceCodeEnd":804,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/model/src/data/bet.rs#L768-L804","documentation":"specified_order_side (crates/model/src/data/bet.rs:778) narrows the three-valued OrderSide (BUY/SELL/NO_ORDER_SIDE) into OrderSideSpecified for the betting conversion functions (probability_to_bet, inverse_probability_to_bet). NO_ORDER_SIDE means \"unset\", so rather than guessing a direction the function bails.","triggerScenarios":"specified_order_side(OrderSide::NoOrderSide), usually indirectly: passing an order whose side was never set into probability_to_bet/inverse_probability_to_bet, or a default-initialized OrderSide enum value.","commonSituations":"Constructing orders without a side; deserialization falling back to the NO_ORDER_SIDE default on missing fields; generic code that converts every order in a collection when some are sideless placeholders.","solutions":["Set the order side (BUY or SELL) before any betting conversion.","Filter or skip orders with OrderSide::NoOrderSide before converting.","Fix the upstream construction or deserialization that leaves the side unset."],"exampleFix":"// before\nlet bet = probability_to_bet(prob, volume, specified_order_side(order.side())?)?;\n\n// after\nlet side = match order.side() {\n    OrderSide::Buy => OrderSideSpecified::Buy,\n    OrderSide::Sell => OrderSideSpecified::Sell,\n    OrderSide::NoOrderSide => {\n        anyhow::bail!(\"order {} has no side; set BUY or SELL first\", order.id())\n    }\n};\nlet bet = probability_to_bet(prob, volume, side)?;","handlingStrategy":"type-guard","validationCode":"if matches!(order.side(), OrderSide::NoOrderSide) {\n    anyhow::bail!(\"order side is unset; set BUY or SELL before betting conversion\");\n}\nlet side = specified_order_side(order.side())?;","typeGuard":"fn has_specified_side(side: OrderSide) -> bool {\n    !matches!(side, OrderSide::NoOrderSide)\n}","tryCatchPattern":"match specified_order_side(order.side()) {\n    Ok(side) => side,\n    Err(e) if e.to_string().contains(\"must be Buy or Sell\") => {\n        anyhow::bail!(\"order {} has no side set\", order.client_order_id())\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always set BUY or SELL when constructing orders destined for betting conversions.","Filter out sideless orders before batch conversion.","Tighten deserialization defaults so a missing side field fails early, not here."],"tags":["betting","order-side","validation"],"backgroundTag":"invalid-order-side","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}