{"record":{"id":"68a4ccf02f8357a9","repo":"nautechsystems/nautilus_trader","slug":"polymarketfeemodel-requires-fee-schedule-exponent","errorCode":null,"errorMessage":"PolymarketFeeModel requires fee schedule exponent 1, was {}","messagePattern":"PolymarketFeeModel requires fee schedule exponent 1, was (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/models.rs","lineNumber":111,"sourceCode":"            .and_then(|value| value.checked_mul(fill_price))\n            .and_then(|value| value.checked_mul(Decimal::ONE - fill_price))\n            .context(\"commission calculation overflow\")?;\n        let commission = match liquidity_side {\n            LiquiditySide::Maker => -fee_equivalent\n                .checked_mul(schedule.rebate_rate)\n                .context(\"commission calculation overflow\")?\n                .round_dp(5),\n            LiquiditySide::Taker => fee_equivalent.round_dp(5),\n            LiquiditySide::NoLiquiditySide => unreachable!(),\n        };\n\n        Money::from_decimal(commission, instrument.quote_currency()).map_err(Into::into)\n    }\n}\n\nfn validate_schedule(schedule: &FeeSchedule) -> anyhow::Result<()> {\n    if schedule.exponent != Decimal::ONE {\n        anyhow::bail!(\n            \"PolymarketFeeModel requires fee schedule exponent 1, was {}\",\n            schedule.exponent\n        );\n    }\n\n    if schedule.rate < Decimal::ZERO {\n        anyhow::bail!(\"Polymarket fee rate must be greater than or equal to zero\");\n    }\n\n    if !(Decimal::ZERO..=Decimal::ONE).contains(&schedule.rebate_rate) {\n        anyhow::bail!(\"Polymarket rebate rate must be in [0, 1]\");\n    }\n\n    if !schedule.taker_only {\n        anyhow::bail!(\"PolymarketFeeModel requires a taker-only fee schedule\");\n    }\n    Ok(())\n}","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/models.rs#L93-L129","documentation":"validate_schedule enforces that the market's FeeSchedule has exponent 1, the only exponent formula PolymarketFeeModel supports for its linear fee computation. A schedule with any other exponent (e.g. Polymarket's historical nonlinear exponent schedules) is rejected.","triggerScenarios":"A market's taker fee schedule (from instrument info) carries exponent != 1 when get_commission runs validate_schedule — e.g. markets whose fee schedule uses a nonlinear exponent.","commonSituations":"Trading markets with legacy or special fee schedules fetched from the CLOB API; fee schedule data drift where the API starts returning exponent 2 or 0.5; hard-coded test fixtures with wrong exponent values.","solutions":["Only apply PolymarketFeeModel to markets whose fee schedule has exponent 1.","Inspect the market's fee_schedule in instrument info and confirm what the CLOB API returns.","Extend validate_schedule/commission math to support the observed exponent if that market type must be supported.","Update stale fee schedule fixtures to exponent 1 if the data is simply outdated."],"exampleFix":"// before\nlet schedule = FeeSchedule { exponent: Decimal::new(2, 0), .. };\n// after\nlet schedule = FeeSchedule { exponent: Decimal::ONE, .. };","handlingStrategy":"validation","validationCode":"if schedule.exponent != Decimal::ONE {\n    return Err(format!(\"unsupported fee exponent {}\", schedule.exponent));\n}","typeGuard":"fn is_linear_schedule(s: &FeeSchedule) -> bool {\n    s.exponent == Decimal::ONE && s.rate >= Decimal::ZERO && (Decimal::ZERO..=Decimal::ONE).contains(&s.rebate_rate)\n}","tryCatchPattern":"match fee_model.get_commission(&order, qty, px, &instrument) {\n    Ok(fee) => fee,\n    Err(e) if e.to_string().contains(\"exponent 1\") => {\n        log::warn!(\"market uses nonlinear fee schedule; skipping fee model\");\n        Money::zero(instrument.quote_currency())\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Check the market's fee schedule exponent when selecting markets to trade.","Validate schedules at instrument build time.","Keep fixtures in sync with the live CLOB API."],"tags":["fees","validation","polymarket","config"],"backgroundTag":"unsupported-config-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"}