{"record":{"id":"5752addfdf13021e","repo":"nautechsystems/nautilus_trader","slug":"trade-quantity-must-be-positive","errorCode":null,"errorMessage":"trade quantity must be positive","messagePattern":"trade quantity must be positive","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/websocket/dispatch.rs","lineNumber":1474,"sourceCode":"    account_id: AccountId,\n    liquidity_side: LiquiditySide,\n    ts_event: UnixNanos,\n    ts_init: UnixNanos,\n) -> anyhow::Result<FillReport> {\n    let venue_order_id = VenueOrderId::from(trade.taker_order_id.as_str());\n    let trade_id = TradeId::from(trade.id.as_str());\n    let order_side = determine_order_side(\n        trade.trader_side,\n        trade.side,\n        trade.asset_id.as_str(),\n        trade.asset_id.as_str(),\n    );\n\n    let size_precision = instrument.size_precision();\n    let price_precision = instrument.price_precision();\n    let size_dec = parse_decimal_exact(&trade.size)?;\n    let price_dec = parse_decimal_exact(&trade.price)?;\n    anyhow::ensure!(size_dec > Decimal::ZERO, \"trade quantity must be positive\");\n    anyhow::ensure!(\n        price_dec > Decimal::ZERO && price_dec < Decimal::ONE,\n        \"trade price must be in (0, 1)\"\n    );\n    let last_qty = Quantity::from_decimal_dp(size_dec, size_precision)?;\n    let last_px = Price::from_decimal_dp(price_dec, price_precision)?;\n\n    let fee_rate = instrument_taker_fee(instrument);\n    let commission_value = compute_commission(\n        fee_rate,\n        instrument_fee_exponent(instrument)?,\n        size_dec,\n        price_dec,\n        liquidity_side,\n    )?;\n    let pusd = crate::execution::get_pusd_currency();\n\n    Ok(FillReport {","sourceCodeStart":1456,"sourceCodeEnd":1492,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/websocket/dispatch.rs#L1456-L1492","documentation":"The Polymarket WebSocket adapter validates parsed trade sizes before constructing a domain Quantity. A trade whose size parses to zero or a negative decimal cannot represent a valid trade quantity, so the adapter aborts dispatch with this anyhow error. It guards against malformed or hostile exchange payloads (e.g. zero-size prints, auction placeholders) entering the trading kernel.","triggerScenarios":"Processing a polymarket trade message whose `size` field parses via parse_decimal_exact to Decimal::ZERO or negative — e.g. a size of \"0\", \"0.0000\", or a malformed negative value from the venue.","commonSituations":"Polymarket venue sending zero-size fills during auction phases or market transitions; upstream API changes emitting placeholder sizes; corrupted/duplicate messages replayed from a snapshot.","solutions":["Log the raw trade payload and check the venue's size field for zero/negative values","Skip or drop the offending message in the dispatch handler rather than failing the stream if zero-size prints are expected","Update the adapter if Polymarket changed its message schema (check newer nautilus versions)","Report the payload to the venue or nautilus-trader maintainers if it is genuinely invalid"],"exampleFix":"// before: whole stream errors on a zero-size print\nanyhow::ensure!(size_dec > Decimal::ZERO, \"trade quantity must be positive\");\n// after: tolerate and skip zero-size prints\nif size_dec <= Decimal::ZERO {\n    log::debug!(\"skipping trade with non-positive size {}\", trade.size);\n    return Ok(None);\n}","handlingStrategy":"validation","validationCode":"let size_dec = parse_decimal_exact(&trade.size)?;\nif size_dec <= Decimal::ZERO {\n    log::warn!(\"skipping trade with non-positive size {}\", trade.size);\n    return Ok(None);\n}","typeGuard":"fn is_positive_size(raw: &str) -> bool {\n    parse_decimal_exact(raw).map(|d| d > Decimal::ZERO).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Check the size field of every venue payload before dispatch","Handle zero-size prints (common in auction phases) explicitly","Keep adapter versions aligned with venue schema changes"],"tags":["polymarket","websocket","validation","decimal"],"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"}