nautechsystems/nautilus_trader · error
builder fee rate must be non-negative
Error message
builder fee rate must be non-negative
What it means
adjust_market_buy_amount requires the builder taker fee rate to be non-negative, since it is used to compute the fee-inclusive total cost. A negative builder_taker_fee_rate is rejected with "builder fee rate must be non-negative".
Source
Thrown at crates/adapters/polymarket/src/execution/parse.rs:530
price: Decimal,
fee_rate: Decimal,
fee_exponent: Decimal,
builder_taker_fee_rate: Decimal,
) -> anyhow::Result<Decimal> {
if price <= Decimal::ZERO || price >= Decimal::ONE {
anyhow::bail!(
"invalid market-buy price {price}: must satisfy 0 < price < 1 for fee adjustment",
);
}
let platform_fee_rate = fee_curve_rate(fee_rate, price, fee_exponent)?;
anyhow::ensure!(amount > Decimal::ZERO, "market-buy amount must be positive");
anyhow::ensure!(
user_pusd_balance > Decimal::ZERO,
"market-buy balance must be positive"
);
anyhow::ensure!(
builder_taker_fee_rate >= Decimal::ZERO,
"builder fee rate must be non-negative"
);
let platform_fee = amount
.checked_div(price)
.and_then(|shares| shares.checked_mul(platform_fee_rate))
.context("market-buy platform fee overflow")?;
let builder_fee = amount
.checked_mul(builder_taker_fee_rate)
.context("market-buy builder fee overflow")?;
let total_cost = amount
.checked_add(platform_fee)
.and_then(|cost| cost.checked_add(builder_fee))
.context("market-buy total cost overflow")?;
let raw = if user_pusd_balance <= total_cost {
let divisor = platform_fee_rate
.checked_div(price)View on GitHub (pinned to 18893faf8b)
Solutions
- Set builder_taker_fee_rate to a non-negative decimal in the fee configuration.
- Check the code path that parses the builder fee from the venue/config and clamp or reject negatives at parse time.
- Confirm rate units and sign conventions for Polymarket builder fees.
Example fix
// before let builder_fee = Decimal::new(-10, 4); // negative adjust_market_buy_amount(amount, price, balance, builder_fee, ...)?; // after let builder_fee = Decimal::new(10, 4); // 0.0010, non-negative adjust_market_buy_amount(amount, price, balance, builder_fee, ...)?;
Defensive patterns
Strategy: validation
Validate before calling
if builder_taker_fee_rate < Decimal::ZERO { return Err("builder fee rate must be >= 0".into()); } Type guard
fn is_non_negative_rate(rate: Decimal) -> bool { rate >= Decimal::ZERO } Prevention
- Validate fee-rate config values (non-negative, sane range) at startup.
- Reject negative rates at config parse time with a clear message.
- Document fee-rate units to avoid sign/unit mixups.
When it happens
Trigger: Calling adjust_market_buy_amount with a builder_taker_fee_rate < 0, usually sourced from a malformed fee configuration or a parse bug producing a signed decimal.
Common situations: Hand-edited config where the builder fee was entered as a negative number; confusion between rate directions (payer vs receiver) causing sign flips; unit mixups (basis points vs fraction) with minus signs.
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
- PolymarketFeeModel requires fee schedule exponent 1, was {}
- event_slug_builder.interval_mins must be positive
- event_slug_builder.periods must be positive
- event_slug_builder.assets must include at least one non-empt
- event_slug_builder offset resolves before the Unix epoch
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/deabcd51fa5f7c44.
Report an issue: GitHub.