{"record":{"id":"fb9b347b713ce329","repo":"nautechsystems/nautilus_trader","slug":"blockchain-execution-transaction-limits-are-requir","errorCode":null,"errorMessage":"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","messagePattern":"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","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":307,"sourceCode":"        let (\n            Some(allowed_token_pairs),\n            Some(slippage_bps),\n            Some(max_slippage_bps),\n            Some(max_order_amount),\n            Some(deadline_seconds),\n            Some(max_quote_age_blocks),\n            Some(receipt_timeout_secs),\n        ) = (\n            &config.allowed_token_pairs,\n            config.slippage_bps,\n            config.max_slippage_bps,\n            config.max_order_amount,\n            config.deadline_seconds,\n            config.max_quote_age_blocks,\n            config.receipt_timeout_secs,\n        )\n        else {\n            anyhow::bail!(\n                \"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\"\n            );\n        };\n\n        let mut parsed_pairs = HashSet::with_capacity(allowed_token_pairs.len());\n        for (token_in, token_out) in allowed_token_pairs {\n            parsed_pairs.insert((\n                validate_address(token_in.as_str())?,\n                validate_address(token_out.as_str())?,\n            ));\n        }\n\n        if slippage_bps > max_slippage_bps {\n            anyhow::bail!(\n                \"`slippage_bps` {slippage_bps} exceeds `max_slippage_bps` {max_slippage_bps}\"\n            );\n        }\n","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/execution/client.rs#L289-L325","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Spell the keys exactly as listed in the error message — serde silently defaults unknown keys to None.","Fail fast at config load: assert each of the seven Options is Some before constructing the client.","Add a config lint or schema check so missing keys are reported by name at startup."],"exampleFix":"// before: limits omitted -> client construction bails\nlet config = BlockchainExecutionClientConfig { /* ... */ ..defaults() };\nlet client = BlockchainExecutionClient::new(config, cache, clock).await?;\n\n// after: all seven required limits provided\nlet config = BlockchainExecutionClientConfig {\n    allowed_token_pairs: Some(vec![(weth.clone(), usdc.clone())]),\n    slippage_bps: Some(50),\n    max_slippage_bps: Some(300),\n    max_order_amount: Some(10_000_000_000),\n    deadline_seconds: Some(120),\n    max_quote_age_blocks: Some(4),\n    receipt_timeout_secs: Some(90),\n    ..config\n};","handlingStrategy":"validation","validationCode":"fn limits_complete(cfg: &BlockchainExecutionClientConfig) -> bool {\n    cfg.allowed_token_pairs.is_some()\n        && cfg.slippage_bps.is_some()\n        && cfg.max_slippage_bps.is_some()\n        && cfg.max_order_amount.is_some()\n        && cfg.deadline_seconds.is_some()\n        && cfg.max_quote_age_blocks.is_some()\n        && cfg.receipt_timeout_secs.is_some()\n}\n// assert at config load, before client construction","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["Spell the seven keys exactly as the error lists them.","Fail fast on None at config load.","Add a CI test that constructs the client from the shipped example config."],"tags":["rust","nautilustrader","config","blockchain","missing-value","evm"],"backgroundTag":"missing-required-config","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}