nautechsystems/nautilus_trader · error

Token manifest identity or asset role is invalid

Error message

Token manifest identity or asset role is invalid

What it means

Each manifest token must have a non-empty trimmed name, a non-empty trimmed symbol, and an asset_role that is exactly one of "base", "quote", or "both". This error means the token exists and is pinned, but its identity metadata or asset role is missing/misspelled, so the adapter cannot classify the token as a swap base or quote asset.

Source

Thrown at crates/adapters/blockchain/src/rpc/verification.rs:1360

        BlockchainContractRole::WrappedNative,
        BlockchainContractRole::Quote,
        BlockchainContractRole::Token,
        BlockchainContractRole::Pool,
    ] {
        anyhow::ensure!(
            roles.contains(&required),
            "Deployment manifest is missing a required role"
        );
    }

    for token in &manifest.tokens {
        let address = Address::from_str(&token.address)
            .map_err(|_| anyhow::anyhow!("Token manifest address is invalid"))?;
        anyhow::ensure!(
            contract_addresses.contains(&address),
            "Token manifest address has no contract identity"
        );
        anyhow::ensure!(
            !token.name.trim().is_empty()
                && !token.symbol.trim().is_empty()
                && matches!(token.asset_role.as_str(), "base" | "quote" | "both"),
            "Token manifest identity or asset role is invalid"
        );
    }

    for pool in &manifest.pools {
        for address in [
            &pool.address,
            &pool.token0,
            &pool.token1,
            &pool.factory,
            &pool.quote_contract,
        ] {
            let address = Address::from_str(address)
                .map_err(|_| anyhow::anyhow!("Pool manifest address is invalid"))?;
            anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set asset_role to exactly "base", "quote", or "both" (lowercase)
  2. Fill in non-empty name and symbol (trim whitespace)
  3. Regenerate the manifest with the generator that emits the expected role vocabulary

Example fix

// before
{"address": "0xabc...", "name": "", "symbol": "USDC", "asset_role": "Base"}
// after
{"address": "0xabc...", "name": "USD Coin", "symbol": "USDC", "asset_role": "quote"}
Defensive patterns

Strategy: validation

Validate before calling

fn token_metadata_ok(t: &TokenEntry) -> bool {
    !t.name.trim().is_empty()
        && !t.symbol.trim().is_empty()
        && matches!(t.asset_role.as_str(), "base" | "quote" | "both")
}
assert!(manifest.tokens.iter().all(token_metadata_ok));

Try / catch

match validate_manifest(&config) {
    Err(e) if e.to_string().contains("identity or asset role") => {
        eprintln!("set non-empty name/symbol and asset_role in {{base,quote,both}}: {e}");
    }
    Err(e) => return Err(e),
    Ok(v) => v,
}

Prevention

When it happens

Trigger: Manifest verification where a token entry has an empty or whitespace-only name/symbol, or asset_role is absent, empty, or any string other than base/quote/both — e.g. asset_role: "Base" (wrong case), "pricing", or "".

Common situations: Hand-adding a token with placeholder metadata; a manifest generator emitting camelCase or a different role vocabulary; truncated JSON edit leaving empty strings; copying a token entry between manifests that use different role conventions.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/3296cb36b7ef3bfb. Report an issue: GitHub.