nautechsystems/nautilus_trader · error · anyhow::Error
Deployment manifest contains a duplicate token identity
Error message
Deployment manifest contains a duplicate token identity
What it means
When populating `token_decimals`, the validator uses `HashMap::insert` and `anyhow::ensure!(insert(...).is_none(), ...)` to reject any address that appears more than once in `manifest.tokens`. This error means two token entries share the same address, so the manifest's token identity set is not unique and decimals would be ambiguous.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:423
.map(|dex| dex.factory)
.ok_or_else(|| {
anyhow::anyhow!(
"No registered Uniswap V3 deployment for chain {}",
config.chain.name
)
})?;
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"
);
}
}View on GitHub (pinned to 18893faf8b)
Solutions
- Remove the duplicate `tokens` entry so each address appears exactly once in the manifest
- If both entries were intentional aliases, keep one canonical entry per contract address
- Regenerate the manifest token list to deduplicate
Example fix
// before
{"symbol": "USDC", "address": "0xA0b8...eB48"},
{"symbol": "USDC_OLD", "address": "0xA0b8...eB48"}
// after
{"symbol": "USDC", "address": "0xA0b8...eB48"} Defensive patterns
Strategy: validation
Validate before calling
let mut seen = HashSet::new();
for t in &manifest.tokens {
let a = Address::from_str(&t.address).unwrap();
if !seen.insert(a) { return Err(format!("duplicate token address {a}")); }
} Prevention
- Deduplicate the tokens array when regenerating or merging manifests
- Key token entries by address in any generation script so duplicates are impossible
- Add a uniqueness assertion to manifest CI checks
When it happens
Trigger: Client validation where `manifest.tokens` contains two entries whose parsed `Address` is equal — exact duplicate rows, or the same address listed under two different symbols/decimals.
Common situations: Appending a token to the manifest that already exists (merge conflict or script rerun); listing the same contract under wrapped and unwrapped names; copy-paste duplicating a token block with an edited symbol but unchanged address.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- heartbeat_secs must be positive when set
- signature_expiry_secs {signature_expiry_secs}s must be great
- Timeout must be greater than 0
- Timeout must be less than 3600 seconds
- VNC port must be between 5900 and 5999
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/157bf8c6e09f3de1.
Report an issue: GitHub.