{"record":{"id":"cf7ba74f23bc4e19","repo":"nautechsystems/nautilus_trader","slug":"deployment-manifest-contains-a-duplicate-call-edge","errorCode":null,"errorMessage":"Deployment manifest contains a duplicate call edge","messagePattern":"Deployment manifest contains a duplicate call edge","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/verification.rs","lineNumber":1410,"sourceCode":"                edge.purpose.as_str(),\n                \"wrap\" | \"approve\" | \"swap_sell\" | \"swap_buy\"\n            ) && matches!(\n                edge.call_type.as_str(),\n                \"call\" | \"staticcall\" | \"delegatecall\" | \"callcode\"\n            ),\n            \"Deployment manifest call edge is invalid\"\n        );\n        let caller = Address::from_str(&edge.caller)\n            .map_err(|_| anyhow::anyhow!(\"Call edge address is invalid\"))?;\n        let target = Address::from_str(&edge.target)\n            .map_err(|_| anyhow::anyhow!(\"Call edge address is invalid\"))?;\n        for address in [caller, target] {\n            anyhow::ensure!(\n                contract_addresses.contains(&address),\n                \"Call edge references an unpinned contract\"\n            );\n        }\n        anyhow::ensure!(\n            call_edges.insert((\n                edge.purpose.as_str(),\n                caller,\n                target,\n                edge.call_type.as_str()\n            )),\n            \"Deployment manifest contains a duplicate call edge\"\n        );\n    }\n\n    for purpose in [\"swap_sell\", \"swap_buy\"] {\n        anyhow::ensure!(\n            manifest\n                .call_edges\n                .iter()\n                .any(|edge| edge.purpose == purpose),\n            \"Deployment manifest is missing a swap call graph\"\n        );","sourceCodeStart":1392,"sourceCodeEnd":1428,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/verification.rs#L1392-L1428","documentation":"Call edges must be unique: the validator inserts a (purpose, caller, target, call_type) tuple into a HashSet and rejects the manifest if the tuple was already present. Duplicate edges add nothing to the call graph and usually indicate an accidental double entry, so they are treated as a manifest defect.","triggerScenarios":"Validating a manifest whose call_edges array contains two entries with identical purpose, caller, target, and call_type (differences in any other field do not matter — the dedup key is those four values).","commonSituations":"Merging manifests or appending generated edges to hand-written ones and duplicating an entry; a generator bug that emits the approve edge twice; copy-paste duplication while editing JSON by hand.","solutions":["Remove the duplicate call_edge entry so each (purpose, caller, target, call_type) combination appears once","If merging manifests, deduplicate call_edges by the four-key tuple before validation","Fix the generator or merge script to deduplicate edges automatically","Diff the call_edges array against a previous valid manifest to spot accidental copies"],"exampleFix":"// before\n{\"call_edges\": [{\"purpose\": \"approve\", \"caller\": \"0xaaa...\", \"target\": \"0xbbb...\", \"call_type\": \"call\"}, {\"purpose\": \"approve\", \"caller\": \"0xaaa...\", \"target\": \"0xbbb...\", \"call_type\": \"call\"}]}\n// after\n{\"call_edges\": [{\"purpose\": \"approve\", \"caller\": \"0xaaa...\", \"target\": \"0xbbb...\", \"call_type\": \"call\"}]}","handlingStrategy":"validation","validationCode":"use std::collections::HashSet;\nlet mut seen: HashSet<(String, String, String, String)> = HashSet::new();\nfor edge in &manifest.call_edges {\n    let key = (edge.purpose.clone(), edge.caller.clone(), edge.target.clone(), edge.call_type.clone());\n    if !seen.insert(key) {\n        return Err(\"duplicate call edge\".into());\n    }\n}","typeGuard":null,"tryCatchPattern":"match validate_deployment_manifest(&manifest) {\n    Err(e) if e.to_string().contains(\"duplicate call edge\") => {\n        eprintln!(\"Deduplicate call_edges by (purpose, caller, target, call_type): {e}\");\n    }\n    Err(e) => return Err(e),\n    Ok(()) => {}\n}","preventionTips":["Deduplicate edges programmatically when merging manifests","Avoid manual copy-paste editing of call_edges arrays","Add a serialization round-trip test that catches duplicated edges in fixtures"],"tags":["blockchain","manifest-validation","duplicate"],"backgroundTag":"schema-validation-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}