nautechsystems/nautilus_trader · error

Quote spend limit `max_amount` '{max_amount}' must be a base

Error message

Quote spend limit `max_amount` '{max_amount}' must be a base-10 unsigned integer string

What it means

A quote spend limit's max_amount must be a non-empty base-10 unsigned integer string (no decimals, signs, or hex), because it is parsed as an on-chain U256 raw amount in the token's smallest unit. The library throws this when the string is empty or contains any non-digit bytes, or when U256::from_str overflows.

Source

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

            let token_out = validate_address(limit.token_out.as_str())?;
            let spend_token = validate_address(limit.spend_token.as_str())?;

            if !parsed_pairs.contains(&(token_in, token_out)) {
                anyhow::bail!(
                    "Quote spend limit pair {token_in} -> {token_out} is not in the `allowed_token_pairs` allowlist"
                );
            }

            if spend_token != token_in {
                anyhow::bail!(
                    "Quote spend limit for {token_in} -> {token_out} is denominated in {spend_token}; `spend_token` must match `token_in`"
                );
            }

            if limit.max_amount.is_empty()
                || !limit.max_amount.bytes().all(|byte| byte.is_ascii_digit())
            {
                anyhow::bail!(
                    "Quote spend limit `max_amount` '{}' must be a base-10 unsigned integer string",
                    limit.max_amount
                );
            }
            let max_amount = U256::from_str(&limit.max_amount).map_err(|_| {
                anyhow::anyhow!(
                    "Quote spend limit `max_amount` '{}' exceeds the U256 range",
                    limit.max_amount
                )
            })?;
            let ceiling = QuoteSpendCeiling {
                spend_token,
                spend_token_decimals: limit.spend_token_decimals,
                max_amount,
            };

            if parsed_quote_spend_limits
                .insert((token_in, token_out), ceiling)

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Provide max_amount as a decimal integer string of the raw token amount (smallest unit)
  2. Convert decimal/float amounts to integer base units before writing config (multiply by token decimals)
  3. Remove any 0x prefix, sign, decimal point, or exponent characters

Example fix

// before
max_amount = "1.5"
// after
max_amount = "1500000000000000000"
Defensive patterns

Strategy: validation

Validate before calling

fn parse_max_amount(s: &str) -> Result<U256, String> {
    if s.is_empty() || !s.bytes().all(|b| b.is_ascii_digit()) {
        return Err(format!("max_amount '{s}' must be a base-10 unsigned integer string"));
    }
    U256::from_str(s).map_err(|e| format!("max_amount '{s}' not representable as U256: {e}"))
}

Prevention

When it happens

Trigger: Calling new/transaction_limits with config.quote_spend_limits entries whose max_amount is "", contains '.', '-', 'e', hex chars, whitespace, or exceeds U256::MAX.

Common situations: Writing a decimal human amount like "1.5" instead of wei-integer "1500000000000000000"; using scientific notation "1e18"; empty value left by a template; pasting a 0x-prefixed hex amount.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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