nautechsystems/nautilus_trader · error

Wallet token {address} does not have exactly one deployment

Error message

Wallet token {address} does not have exactly one deployment manifest identity

What it means

When building a `Token` from the wallet, the adapter looks up the token address in the deployment manifest and requires exactly one matching identity. This `ensure!` fails when the number of manifest identities whose `address` parses to the given address is zero or greater than one, so the canonical token identity is ambiguous or missing.

Source

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

        "finalized native balance",
    )?;
    let native_balance = Money::from_u256(native_amount.value, plan.pool.chain.native_currency())?;
    let mut decisions = vec![verification_decision(
        &native_amount,
        Some(included.block_number),
        Some(included.block_number),
    )];
    let mut token_addresses = token_universe.iter().copied().collect::<Vec<_>>();
    token_addresses.sort_unstable();
    let mut token_balances = Vec::with_capacity(token_addresses.len());
    for address in token_addresses {
        let identities = executor
            .deployment_manifest
            .tokens
            .iter()
            .filter(|identity| Address::from_str(&identity.address).ok() == Some(address))
            .collect::<Vec<_>>();
        anyhow::ensure!(
            identities.len() == 1,
            "Wallet token {address} does not have exactly one deployment manifest identity"
        );
        let identity = identities[0];
        let token = Token::new(
            plan.pool.chain.clone(),
            address,
            identity.name.clone(),
            identity.symbol.clone(),
            identity.decimals,
        );
        let call = ERC20::balanceOfCall {
            account: executor.wallet_address,
        }
        .abi_encode();
        let amount = required_verification(
            executor
                .verification

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Deduplicate the token entries in the deployment manifest so the address appears exactly once
  2. Add the missing token identity to the deployment manifest if it is absent
  3. Ensure manifest addresses are canonical checksummed/lowercase and parse to the intended `Address`
  4. Regenerate the manifest from the deployment source rather than editing it by hand

Example fix

// before: manifest with duplicate
{"tokens": [{"address": "0xABC..."}, {"address": "0xABC..."}]}
// after: single canonical entry
{"tokens": [{"address": "0xAbC...", "decimals": 18, "symbol": "WETH"}]}
Defensive patterns

Strategy: validation

Validate before calling

// before execution, confirm the token resolves uniquely
let matches: Vec<_> = manifest.tokens.iter()
    .filter(|t| Address::from_str(&t.address).ok() == Some(token_address))
    .collect();
ensure!(matches.len() == 1, "token {token_address} must appear exactly once in the manifest");

Type guard

fn unique_token_identity(manifest: &DeploymentManifest, address: Address) -> bool {
    manifest.tokens.iter()
        .filter(|t| Address::from_str(&t.address).ok() == Some(address))
        .count() == 1
}

Try / catch

if let Err(e) = execute_plan(&plan).await {
    if e.to_string().contains("exactly one deployment manifest identity") {
        log::error!("fix manifest: deduplicate or add the token identity");
    }
}

Prevention

When it happens

Trigger: Executing a plan whose pool token address (1) is not present in `deployment_manifest.tokens`, or (2) appears in multiple identity entries (duplicate addresses, e.g. same token listed under different symbols/decimals or duplicated across chains in the manifest).

Common situations: Hand-edited or merged deployment manifest with duplicated token entries; a wallet token address from a testnet manifest used against a mainnet manifest; case/parity handling differences causing `Address::from_str` to resolve two entries to the same address; token added to the manifest twice during a deployment update.

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/83b3649199345848. Report an issue: GitHub.