nautechsystems/nautilus_trader · error
Polymarket rebate rate must be in [0, 1]
Error message
Polymarket rebate rate must be in [0, 1]
What it means
validate_schedule requires the schedule's rebate_rate to be within [0, 1] because it is treated as a proportion. A rebate rate outside this interval is invalid input and would corrupt fee/rebate math, so validation bails.
Source
Thrown at crates/adapters/polymarket/src/models.rs:122
Money::from_decimal(commission, instrument.quote_currency()).map_err(Into::into)
}
}
fn validate_schedule(schedule: &FeeSchedule) -> anyhow::Result<()> {
if schedule.exponent != Decimal::ONE {
anyhow::bail!(
"PolymarketFeeModel requires fee schedule exponent 1, was {}",
schedule.exponent
);
}
if schedule.rate < Decimal::ZERO {
anyhow::bail!("Polymarket fee rate must be greater than or equal to zero");
}
if !(Decimal::ZERO..=Decimal::ONE).contains(&schedule.rebate_rate) {
anyhow::bail!("Polymarket rebate rate must be in [0, 1]");
}
if !schedule.taker_only {
anyhow::bail!("PolymarketFeeModel requires a taker-only fee schedule");
}
Ok(())
}
#[cfg(test)]
mod tests {
use nautilus_core::UnixNanos;
use nautilus_execution::models::fee::{FeeModel, FeeModelHandle};
use nautilus_model::{
enums::{LiquiditySide, OrderSide, OrderType},
instruments::{Instrument, InstrumentAny, stubs::audusd_sim},
orders::{OrderAny, builder::OrderTestBuilder, stubs::TestOrderStubs},
types::{Price, Quantity},
};View on GitHub (pinned to 18893faf8b)
Solutions
- Normalize rebate_rate to a 0–1 fraction (divide percent values by 100) before constructing FeeSchedule.
- Verify how the CLOB API encodes rebate_rate and fix the deserialization accordingly.
- Validate schedules at instrument construction time to fail fast before trading.
- Correct any fixture with rebate_rate outside [0, 1].
Example fix
// before
let schedule = FeeSchedule { rebate_rate: Decimal::from(25), .. }; // percent
// after
let schedule = FeeSchedule { rebate_rate: Decimal::new(25, 2), .. }; // 0.25 Defensive patterns
Strategy: validation
Validate before calling
if !(Decimal::ZERO..=Decimal::ONE).contains(&schedule.rebate_rate) {
return Err("rebate_rate must be a fraction in [0,1]".into());
} Type guard
fn has_valid_rebate_rate(s: &FeeSchedule) -> bool {
(Decimal::ZERO..=Decimal::ONE).contains(&s.rebate_rate)
} Try / catch
match fee_model.get_commission(&order, qty, px, &instrument) {
Ok(fee) => fee,
Err(e) if e.to_string().contains("rebate rate must be in [0, 1]") => {
log::error!("rebate_rate out of range — check percent vs fraction");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Normalize percent-encoded schedule fields to fractions on ingestion.
- Clamp or reject rebate rates outside [0,1] at deserialization time.
- Cross-check schedule values against the CLOB API in integration tests.
When it happens
Trigger: get_commission on a market whose FeeSchedule.rebate_rate is negative or greater than 1 — typically from misparsed API data (percent vs fraction) or bad fixtures.
Common situations: Fee schedule fields given as percentages (e.g. 25 meaning 0.25) by upstream data; corrupted or hand-edited fixtures; parsing errors mapping JSON fields to Decimal.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- PolymarketFeeModel requires a fill price in [0, 1]
- PolymarketFeeModel requires fee schedule exponent 1, was {}
- Polymarket fee rate must be greater than or equal to zero
- builder fee rate must be non-negative
- fee quantity must be non-negative
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/beb8908b810237e5.
Report an issue: GitHub.