nautechsystems/nautilus_trader · error

No `quote_spend_limits` entry for BUY token pair {token_in}

Error message

No `quote_spend_limits` entry for BUY token pair {token_in} -> {token_out}

What it means

BUY swaps spend the quote token, and the adapter enforces a per-pair quote-spend ceiling. `transaction_limits.quote_spend_limits` has no entry for the (token_in, token_out) pair, so a BUY order cannot be cost-capped and is rejected.

Source

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

                anyhow::anyhow!("slippage_bps parameter {value} exceeds the u32 range")
            })?,
            None => self.transaction_limits.slippage_bps,
        };

        if slippage_bps > self.transaction_limits.max_slippage_bps {
            anyhow::bail!(
                "Slippage {slippage_bps} bps exceeds the configured `max_slippage_bps` {}",
                self.transaction_limits.max_slippage_bps
            );
        }

        let quote_spend_ceiling = if order.order_side() == OrderSide::Buy {
            let ceiling = self
                .transaction_limits
                .quote_spend_limits
                .get(&(token_in, token_out))
                .ok_or_else(|| {
                    anyhow::anyhow!(
                        "No `quote_spend_limits` entry for BUY token pair {token_in} -> {token_out}"
                    )
                })?;
            anyhow::ensure!(
                ceiling.spend_token == quote_token.address,
                "Quote spend limit for {token_in} -> {token_out} is denominated in {}, expected quote token {}",
                ceiling.spend_token,
                quote_token.address
            );
            anyhow::ensure!(
                ceiling.spend_token_decimals == quote_token.decimals,
                "Quote spend limit for token {} uses {} decimals, expected pool quote-token decimals {}",
                ceiling.spend_token,
                ceiling.spend_token_decimals,
                quote_token.decimals
            );
            Some(ceiling)
        } else {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add a `quote_spend_limits` entry keyed by the exact (token_in, token_out) pair used by the order
  2. Verify the token addresses in the map match the pool's token addresses exactly (same checksum/case)
  3. Either configure limits for all BUY pairs you trade, or route the order as a SELL-side pair if appropriate

Example fix

// before
quote_spend_limits: {} 
// after
quote_spend_limits: {
  (usdc_addr, weth_addr): QuoteSpendCeiling { spend_token: usdc_addr, spend_token_decimals: 6, max_spend: ... },
}
Defensive patterns

Strategy: validation

Validate before calling

if order.order_side() == OrderSide::Buy
    && !transaction_limits.quote_spend_limits.contains_key(&(token_in, token_out)) {
    return Err(format!("add quote_spend_limits entry for {token_in} -> {token_out}"));
}

Type guard

fn has_spend_limit(limits: &HashMap<(Address, Address), Ceiling>, tin: Address, tout: Address) -> bool {
    limits.contains_key(&(tin, tout))
}

Try / catch

match client.submit_order(buy_order).await {
    Err(e) if e.to_string().contains("No `quote_spend_limits` entry") => {
        // block trading this pair until an operator configures a ceiling
        disable_pair(token_in, token_out);
        Err(e)
    }
    r => r,
}

Prevention

When it happens

Trigger: `submit_order()` -> `prepare_swap()` with `order.order_side() == OrderSide::Buy` and no `quote_spend_limits` map entry keyed by the exact (token_in, token_out) address pair.

Common situations: Configured spend limits for the inverse direction only; token address casing/checksum mismatch as map key; new market added to trading config without adding its spend-limit entry.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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