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

  1. Set builder_taker_fee_rate to a non-negative decimal in the fee configuration.
  2. Check the code path that parses the builder fee from the venue/config and clamp or reject negatives at parse time.
  3. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/deabcd51fa5f7c44. Report an issue: GitHub.