nautechsystems/nautilus_trader · error
Duplicate quote spend limit for token pair {token_in} -> {to
Error message
Duplicate quote spend limit for token pair {token_in} -> {token_out} What it means
Each (token_in, token_out) pair may have at most one quote spend limit; the parsed map insert returns Some on a duplicate key. The library throws this to keep the limits map unambiguous rather than silently overwriting a ceiling.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:332
);
}
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)
.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");
}View on GitHub (pinned to 18893faf8b)
Solutions
- Remove the duplicate quote_spend_limits entry, keeping the stricter (smaller) max_amount if unsure
- Deduplicate the list before writing config (unique by token pair)
- Check config merge/diff tooling for accidental duplication
Example fix
// before
quote_spend_limits = [
{ token_in = "0xA", token_out = "0xB", spend_token = "0xA", max_amount = "100" },
{ token_in = "0xA", token_out = "0xB", spend_token = "0xA", max_amount = "200" }
]
// after
quote_spend_limits = [
{ token_in = "0xA", token_out = "0xB", spend_token = "0xA", max_amount = "100" }
] Defensive patterns
Strategy: validation
Validate before calling
let mut seen = HashSet::new();
for l in &cfg.quote_spend_limits {
if !seen.insert((l.token_in.clone(), l.token_out.clone())) {
return Err(format!("duplicate quote spend limit for {} -> {}", l.token_in, l.token_out));
}
} Prevention
- Deduplicate limits in the config build pipeline (e.g. BTreeMap keyed by pair)
- Watch for duplicates introduced by merging environment overlays
- Keep one limit block per pair in the canonical config
When it happens
Trigger: Calling new/transaction_limits with config.quote_spend_limits containing two entries whose validated (token_in, token_out) pairs are equal (e.g. same addresses differing only in checksum casing before validation).
Common situations: Merged config files appending duplicate limit blocks; same pair listed twice with different max_amounts by mistake; duplicated entries after YAML/TOML merge tooling.
Related errors
- request_rate_per_second must be greater than zero
- order_request_rate_per_second must be greater than zero
- heartbeat_secs must be positive when set
- heartbeat_timeout_secs must cover at least two server heartb
- `router_addresses` must contain at least one router address
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/115b34177b288acd.
Report an issue: GitHub.