{"record":{"id":"775c533fbb63fc6d","repo":"nautechsystems/nautilus_trader","slug":"field-value-must-be-positive","errorCode":null,"errorMessage":"{field} {value} must be positive","messagePattern":"(.+?) (.+?) must be positive","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/reconciliation.rs","lineNumber":279,"sourceCode":"        \"provider outcome {outcome} does not match instrument outcome {instrument_outcome}\",\n    );\n\n    Ok(())\n}\n\nfn validate_quantity_evidence(\n    value: Decimal,\n    precision: u8,\n    field: &str,\n    allow_zero: bool,\n) -> anyhow::Result<()> {\n    if allow_zero {\n        anyhow::ensure!(\n            value >= Decimal::ZERO,\n            \"{field} {value} must be non-negative\"\n        );\n    } else {\n        anyhow::ensure!(value > Decimal::ZERO, \"{field} {value} must be positive\");\n    }\n\n    let quantity = Quantity::from_decimal_dp(value, precision).with_context(|| {\n        format!(\"failed to represent {field} {value} with quantity precision {precision}\")\n    })?;\n    anyhow::ensure!(\n        quantity.as_decimal() == value,\n        \"{field} {value} is not exactly representable with quantity precision {precision}\",\n    );\n    Ok(())\n}\n\nfn validate_price_evidence(value: Decimal, precision: u8, field: &str) -> anyhow::Result<()> {\n    anyhow::ensure!(\n        value > Decimal::ZERO && value < Decimal::ONE,\n        \"{field} {value} must be greater than zero and less than one\",\n    );\n    let price = Price::from_decimal_dp(value, precision).with_context(|| {","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/reconciliation.rs#L261-L297","documentation":"validate_quantity_evidence requires strictly positive decimals when allow_zero is false. This error fires when a required quantity field (e.g. an order size or trade amount that must be > 0) is zero or negative.","triggerScenarios":"validate_order_row_values or validate_trade_values calls validate_quantity_evidence with allow_zero=false and the Decimal value is 0 or negative — e.g. a trade row with size 0, or an order row where the filled quantity is zero.","commonSituations":"Provider emitting placeholder rows with zero sizes (dust, cancelled-before-fill); a partially parsed field defaulting to 0 because the real value was missing; division/rounding upstream producing 0.","solutions":["Check the raw provider payload for the field: a 0 here usually means the value was missing or defaulted, not genuinely zero.","Guard upstream: skip zero-size rows before reconciliation instead of failing the whole batch.","Verify parsing (string-to-Decimal) is not silently yielding 0 for empty or malformed values.","If zero is legitimately possible for this field, call validate_quantity_evidence with allow_zero=true."],"exampleFix":"// before\nvalidate_quantity_evidence(trade.size, precision, \"size\", false)?;\n// after\nif trade.size.is_zero() {\n    return Ok(()); // skip empty rows emitted by provider\n}\nvalidate_quantity_evidence(trade.size, precision, \"size\", false)?;","handlingStrategy":"validation","validationCode":"fn is_positive(v: Decimal) -> bool { v > Decimal::ZERO }","typeGuard":null,"tryCatchPattern":"match validate_quantity_evidence(size, precision, \"size\", false) {\n    Err(e) if e.to_string().contains(\"must be positive\") => { skip_trade(trade.id); Ok(()) }\n    other => other,\n}","preventionTips":["Skip zero-size provider rows before reconciliation","Check that Decimal parsing of empty/missing fields fails loudly instead of yielding 0","Review upstream arithmetic that can produce 0 via subtraction or rounding"],"tags":["rust","validation","decimal","quantity"],"backgroundTag":"value-out-of-range","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"}