nautechsystems/nautilus_trader · error · anyhow::Error

Deployment manifest has no wrapped native token identity

Error message

Deployment manifest has no wrapped native token identity

What it means

After building the token table, `validate_manifest_contracts` checks `token_decimals.contains_key(&weth)` and fails with this error when the wrapped-native token address (resolved from the `WrappedNative` role / `weth_address`) is not present among the manifest's token identities. The library requires decimals for the wrapped native token because routing and pricing math depends on it.

Source

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

                    )
                })?;
        anyhow::ensure!(
            factory == registered_factory,
            "Deployment manifest factory does not match the registered Uniswap V3 factory"
        );
        let quote_contract = singleton(BlockchainContractRole::Quote, "quote")?;

        let mut token_decimals = HashMap::new();

        for token in &manifest.tokens {
            let address = Address::from_str(&token.address)
                .map_err(|_| anyhow::anyhow!("Deployment manifest token address is invalid"))?;
            anyhow::ensure!(
                token_decimals.insert(address, token.decimals).is_none(),
                "Deployment manifest contains a duplicate token identity"
            );
        }
        anyhow::ensure!(
            token_decimals.contains_key(&weth),
            "Deployment manifest has no wrapped native token identity"
        );

        if let Some(tokens) = &config.tokens {
            for token in tokens {
                let address = validate_address(token)?;
                anyhow::ensure!(
                    token_decimals.contains_key(&address),
                    "Configured token {address} has no deployment manifest identity"
                );
            }
        }

        for (token_in, token_out) in config.allowed_token_pairs.as_deref().unwrap_or_default() {
            let token_in = validate_address(token_in)?;
            let token_out = validate_address(token_out)?;
            anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add a `tokens` entry for the wrapped-native address with its correct decimals (18 for WETH on most chains)
  2. Regenerate the manifest so wrapped native is included in the token identities
  3. Verify `weth_address` matches the wrapped-native token actually listed in the manifest

Example fix

// before: manifest.tokens lacks WETH
// after
{"symbol": "WETH", "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals": 18}
Defensive patterns

Strategy: validation

Validate before calling

let weth = config.weth_address;
assert!(manifest.tokens.iter().any(|t| Address::from_str(&t.address).map(|a| a == weth).unwrap_or(false)),
        "manifest.tokens must include the wrapped native token {weth}");

Prevention

When it happens

Trigger: Client validation where the manifest's `tokens` array has no entry whose address equals the configured wrapped-native (`weth`) address — the contract entry exists under `contracts` but the corresponding token identity with decimals is missing.

Common situations: Creating a manifest for a new chain and forgetting to add WETH/WMATIC to the tokens list; deleting the wrapped-native token row while trimming the manifest; a mismatch where `weth_address` points to a different token than the one listed in `tokens`.

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/1fcf75d10b38e6b5. Report an issue: GitHub.