{"record":{"id":"f44343123023c8ec","repo":"nautechsystems/nautilus_trader","slug":"fee-rate-must-be-non-negative","errorCode":null,"errorMessage":"fee rate must be non-negative","messagePattern":"fee rate must be non-negative","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/parse.rs","lineNumber":611,"sourceCode":") -> anyhow::Result<Decimal> {\n    anyhow::ensure!(size >= Decimal::ZERO, \"fee quantity must be non-negative\");\n    let rate = fee_curve_rate(fee_rate, price, fee_exponent)?;\n\n    if liquidity_side != LiquiditySide::Taker {\n        return Ok(Decimal::ZERO);\n    }\n    let commission = size\n        .checked_mul(rate)\n        .context(\"commission calculation overflow\")?;\n    Ok(commission.round_dp(5))\n}\n\nfn fee_curve_rate(\n    fee_rate: Decimal,\n    price: Decimal,\n    fee_exponent: Decimal,\n) -> anyhow::Result<Decimal> {\n    anyhow::ensure!(fee_rate >= Decimal::ZERO, \"fee rate must be non-negative\");\n    anyhow::ensure!(\n        fee_exponent >= Decimal::ZERO,\n        \"fee exponent must be non-negative\"\n    );\n    anyhow::ensure!(\n        (Decimal::ZERO..=Decimal::ONE).contains(&price),\n        \"fee price must be in [0, 1]\"\n    );\n\n    if fee_rate.is_zero() {\n        return Ok(Decimal::ZERO);\n    }\n    let base = price * (Decimal::ONE - price);\n    let base_f64: f64 = base\n        .try_into()\n        .context(\"fee curve base is not representable\")?;\n    let exponent_f64: f64 = fee_exponent\n        .try_into()","sourceCodeStart":593,"sourceCodeEnd":629,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/parse.rs#L593-L629","documentation":"The Polymarket adapter's fee_curve_rate validates that the configured maker/taker fee rate is non-negative before computing a curve-based fee. A negative fee rate would produce nonsensical negative commissions, so the adapter rejects it early with anyhow::ensure!. This is an input-validation guard on fee parameters parsed from venue config or fee data.","triggerScenarios":"Calling adjust_market_buy_amount or compute_commission (which call fee_curve_rate) with a fee_rate < 0 — e.g. a config value of '-0.001' for a maker fee rate, or a sign-flipped fee parsed from venue data.","commonSituations":"Misconfiguration in fee settings where fees are entered as negative 'discounts'; parsing fee rates from venue responses with inconsistent sign conventions.","solutions":["Check the fee-rate config value passed to compute_commission/adjust_market_buy_amount and remove the leading minus sign.","Clamp or validate fee_rate >= 0 at config-load time so invalid values fail at startup, not mid-order.","If the fee comes from a parsed venue payload, verify the parser applies the venue's sign convention correctly."],"exampleFix":"// before\nlet fee_rate = Decimal::from_str(\"-0.001\")?;\nlet fee = compute_commission(fee_rate, price, fee_exponent)?;\n// after\nlet fee_rate = Decimal::from_str(\"0.001\")?;\nassert!(fee_rate >= Decimal::ZERO);\nlet fee = compute_commission(fee_rate, price, fee_exponent)?;","handlingStrategy":"validation","validationCode":"if fee_rate < Decimal::ZERO { return Err(anyhow!(\"fee rate must be non-negative: {fee_rate}\")); }","typeGuard":"fn is_valid_fee_rate(rate: Decimal) -> bool { rate >= Decimal::ZERO }","tryCatchPattern":null,"preventionTips":["Validate fee settings at config load time","Never encode fee discounts as negative rates","Add unit tests covering fee boundary values"],"tags":["rust","validation","fees","polymarket"],"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-14T00:17:10.932Z"}