nautechsystems/nautilus_trader · critical

`max_slippage_bps` {max_slippage_bps} must be below {BPS_DEN

Error message

`max_slippage_bps` {max_slippage_bps} must be below {BPS_DENOMINATOR}

What it means

max_slippage_bps is a basis-point ceiling and must be strictly below BPS_DENOMINATOR (10000). The library throws this when the ceiling is 10000 or more, which would permit 100% or more slippage — an invalid/nonsensical bound that could allow complete value loss on a swap.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:345

            if parsed_quote_spend_limits
                .insert((token_in, token_out), ceiling)
                .is_some()
            {
                anyhow::bail!(
                    "Duplicate quote spend limit for token pair {token_in} -> {token_out}"
                );
            }
        }

        if slippage_bps > max_slippage_bps {
            anyhow::bail!(
                "`slippage_bps` {slippage_bps} exceeds `max_slippage_bps` {max_slippage_bps}"
            );
        }

        if max_slippage_bps >= BPS_DENOMINATOR {
            anyhow::bail!("`max_slippage_bps` {max_slippage_bps} must be below {BPS_DENOMINATOR}");
        }

        if !(1..=4_095).contains(&max_quote_age_blocks) {
            anyhow::bail!("`max_quote_age_blocks` must be in 1..=4095");
        }

        Ok(TransactionLimits {
            allowed_token_pairs: parsed_pairs,
            quote_spend_limits: parsed_quote_spend_limits,
            slippage_bps,
            max_slippage_bps,
            max_order_amount,
            deadline_seconds,
            max_quote_age_blocks,
            receipt_timeout_secs,
        })
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set max_slippage_bps to a value in 0..10000 (e.g. 500 = 5%)
  2. Convert any percent-based figure: bps = percent * 100
  3. Re-check the intent: values >= 10000 are never valid

Example fix

// before
max_slippage_bps = 10000
// after
max_slippage_bps = 500
Defensive patterns

Strategy: validation

Validate before calling

const BPS_DENOMINATOR: u64 = 10_000;
if cfg.max_slippage_bps >= BPS_DENOMINATOR {
    return Err(format!("max_slippage_bps {} must be below 10000", cfg.max_slippage_bps));
}

Prevention

When it happens

Trigger: Calling new/transaction_limits with config.max_slippage_bps >= 10000.

Common situations: Confusing percent (100) with basis points (10000) and entering 10000 for '100%'; typos adding a zero; misconfigured limit of e.g. 50000 meaning 50% (should be 5000).

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


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