nautechsystems/nautilus_trader · error
fee rate must be non-negative
Error message
fee rate must be non-negative
What it means
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.
Source
Thrown at crates/adapters/polymarket/src/execution/parse.rs:611
) -> anyhow::Result<Decimal> {
anyhow::ensure!(size >= Decimal::ZERO, "fee quantity must be non-negative");
let rate = fee_curve_rate(fee_rate, price, fee_exponent)?;
if liquidity_side != LiquiditySide::Taker {
return Ok(Decimal::ZERO);
}
let commission = size
.checked_mul(rate)
.context("commission calculation overflow")?;
Ok(commission.round_dp(5))
}
fn fee_curve_rate(
fee_rate: Decimal,
price: Decimal,
fee_exponent: Decimal,
) -> anyhow::Result<Decimal> {
anyhow::ensure!(fee_rate >= Decimal::ZERO, "fee rate must be non-negative");
anyhow::ensure!(
fee_exponent >= Decimal::ZERO,
"fee exponent must be non-negative"
);
anyhow::ensure!(
(Decimal::ZERO..=Decimal::ONE).contains(&price),
"fee price must be in [0, 1]"
);
if fee_rate.is_zero() {
return Ok(Decimal::ZERO);
}
let base = price * (Decimal::ONE - price);
let base_f64: f64 = base
.try_into()
.context("fee curve base is not representable")?;
let exponent_f64: f64 = fee_exponent
.try_into()View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
let fee_rate = Decimal::from_str("-0.001")?;
let fee = compute_commission(fee_rate, price, fee_exponent)?;
// after
let fee_rate = Decimal::from_str("0.001")?;
assert!(fee_rate >= Decimal::ZERO);
let fee = compute_commission(fee_rate, price, fee_exponent)?; Defensive patterns
Strategy: validation
Validate before calling
if fee_rate < Decimal::ZERO { return Err(anyhow!("fee rate must be non-negative: {fee_rate}")); } Type guard
fn is_valid_fee_rate(rate: Decimal) -> bool { rate >= Decimal::ZERO } Prevention
- Validate fee settings at config load time
- Never encode fee discounts as negative rates
- Add unit tests covering fee boundary values
When it happens
Trigger: 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.
Common situations: Misconfiguration in fee settings where fees are entered as negative 'discounts'; parsing fee rates from venue responses with inconsistent sign conventions.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- fee price must be in [0, 1]
- 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
- Polymarket rebate rate must be in [0, 1]
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f44343123023c8ec.
Report an issue: GitHub.