nautechsystems/nautilus_trader · error · anyhow::Error

Blockchain execution transaction limits are required: allowe

Error message

Blockchain execution transaction limits are required: allowed_token_pairs, slippage_bps, max_slippage_bps, max_order_amount, deadline_seconds, max_quote_age_blocks, receipt_timeout_secs

What it means

The blockchain execution client refuses to sign or broadcast anything without hard transaction limits. Its constructor destructures seven Option fields of `BlockchainExecutionClientConfig` — allowed_token_pairs, slippage_bps, max_slippage_bps, max_order_amount, deadline_seconds, max_quote_age_blocks, receipt_timeout_secs — and bails if any is None. Because the fields are Option, a config that omits them still type-checks and only fails at client construction.

Source

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

        let (
            Some(allowed_token_pairs),
            Some(slippage_bps),
            Some(max_slippage_bps),
            Some(max_order_amount),
            Some(deadline_seconds),
            Some(max_quote_age_blocks),
            Some(receipt_timeout_secs),
        ) = (
            &config.allowed_token_pairs,
            config.slippage_bps,
            config.max_slippage_bps,
            config.max_order_amount,
            config.deadline_seconds,
            config.max_quote_age_blocks,
            config.receipt_timeout_secs,
        )
        else {
            anyhow::bail!(
                "Blockchain execution transaction limits are required: allowed_token_pairs, slippage_bps, max_slippage_bps, max_order_amount, deadline_seconds, max_quote_age_blocks, receipt_timeout_secs"
            );
        };

        let mut parsed_pairs = HashSet::with_capacity(allowed_token_pairs.len());
        for (token_in, token_out) in allowed_token_pairs {
            parsed_pairs.insert((
                validate_address(token_in.as_str())?,
                validate_address(token_out.as_str())?,
            ));
        }

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

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Set all seven fields in BlockchainExecutionClientConfig: allowed_token_pairs, slippage_bps, max_slippage_bps, max_order_amount, deadline_seconds, max_quote_age_blocks, receipt_timeout_secs.
  2. Spell the keys exactly as listed in the error message — serde silently defaults unknown keys to None.
  3. Fail fast at config load: assert each of the seven Options is Some before constructing the client.
  4. Add a config lint or schema check so missing keys are reported by name at startup.

Example fix

// before: limits omitted -> client construction bails
let config = BlockchainExecutionClientConfig { /* ... */ ..defaults() };
let client = BlockchainExecutionClient::new(config, cache, clock).await?;

// after: all seven required limits provided
let config = BlockchainExecutionClientConfig {
    allowed_token_pairs: Some(vec![(weth.clone(), usdc.clone())]),
    slippage_bps: Some(50),
    max_slippage_bps: Some(300),
    max_order_amount: Some(10_000_000_000),
    deadline_seconds: Some(120),
    max_quote_age_blocks: Some(4),
    receipt_timeout_secs: Some(90),
    ..config
};
Defensive patterns

Strategy: validation

Validate before calling

fn limits_complete(cfg: &BlockchainExecutionClientConfig) -> bool {
    cfg.allowed_token_pairs.is_some()
        && cfg.slippage_bps.is_some()
        && cfg.max_slippage_bps.is_some()
        && cfg.max_order_amount.is_some()
        && cfg.deadline_seconds.is_some()
        && cfg.max_quote_age_blocks.is_some()
        && cfg.receipt_timeout_secs.is_some()
}
// assert at config load, before client construction

Try / catch

Treat construction failure as fatal configuration error: log the seven field names from the message against the parsed config file and report which keys are absent/misspelled. Do not retry.

Prevention

When it happens

Trigger: Building the client from a config where at least one of the seven fields is missing: a minimal example config, a JSON/TOML key typo (serde leaves the default None), or a test config with limits deliberately stripped.

Common situations: Copying a doc example that predates the required-limits change; typos like 'max_quote_age' vs 'max_quote_age_blocks'; environment-specific config files that drifted.

Understand the failure class

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/fb9b347b713ce329. Report an issue: GitHub.