{"record":{"id":"fef4ec3c869c19ff","repo":"nautechsystems/nautilus_trader","slug":"deployment-manifest-is-missing-a-required-role","errorCode":null,"errorMessage":"Deployment manifest is missing a required role","messagePattern":"Deployment manifest is missing a required role","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/verification.rs","lineNumber":1347,"sourceCode":"            })?;\n        anyhow::ensure!(\n            target_contract.role == BlockchainContractRole::Implementation\n                && target_contract\n                    .runtime_code_hash\n                    .eq_ignore_ascii_case(&proxy.target_code_hash),\n            \"Proxy target role or code hash conflicts with its deployment identity\"\n        );\n    }\n\n    for required in [\n        BlockchainContractRole::Router,\n        BlockchainContractRole::Factory,\n        BlockchainContractRole::WrappedNative,\n        BlockchainContractRole::Quote,\n        BlockchainContractRole::Token,\n        BlockchainContractRole::Pool,\n    ] {\n        anyhow::ensure!(\n            roles.contains(&required),\n            \"Deployment manifest is missing a required role\"\n        );\n    }\n\n    for token in &manifest.tokens {\n        let address = Address::from_str(&token.address)\n            .map_err(|_| anyhow::anyhow!(\"Token manifest address is invalid\"))?;\n        anyhow::ensure!(\n            contract_addresses.contains(&address),\n            \"Token manifest address has no contract identity\"\n        );\n        anyhow::ensure!(\n            !token.name.trim().is_empty()\n                && !token.symbol.trim().is_empty()\n                && matches!(token.asset_role.as_str(), \"base\" | \"quote\" | \"both\"),\n            \"Token manifest identity or asset role is invalid\"\n        );","sourceCodeStart":1329,"sourceCodeEnd":1365,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/verification.rs#L1329-L1365","documentation":"The validator collects the set of BlockchainContractRole values declared across manifest.contracts and requires that every role needed by the adapter's routing flow is present: Router, Factory, WrappedNative, Quote, Token, and Pool. This error means at least one of these required roles has no contract entry in the deployment manifest, so the verifier cannot pin the full on-chain contract topology.","triggerScenarios":"Running manifest verification on a manifest whose contracts[] omit any contract with role Router, Factory, WrappedNative, Quote, Token, or Pool — e.g. generating a minimal manifest with only the implementation contract, or dropping a role during a hand edit.","commonSituations":"New chain onboarding where only some contracts were deployed/registered yet; a manifest template that predates a newly required role; script filtering contracts by allowlist and dropping one; renames of role enum values between manifest versions.","solutions":["Add contract entries covering all six required roles (Router, Factory, WrappedNative, Quote, Token, Pool) with valid addresses and runtime code hashes","Deploy/register the missing contracts, then regenerate the manifest","Check for role enum renames between manifest versions and update the generator"],"exampleFix":"// before\n\"contracts\": [{\"role\": \"router\", ...}, {\"role\": \"factory\", ...}]\n// after\n\"contracts\": [{\"role\": \"router\", ...}, {\"role\": \"factory\", ...}, {\"role\": \"wrapped_native\", ...}, {\"role\": \"quote\", ...}, {\"role\": \"token\", ...}, {\"role\": \"pool\", ...}]","handlingStrategy":"validation","validationCode":"const REQUIRED: [Role; 6] = [Role::Router, Role::Factory, Role::WrappedNative, Role::Quote, Role::Token, Role::Pool];\nlet roles: HashSet<Role> = manifest.contracts.iter().map(|c| c.role).collect();\nassert!(REQUIRED.iter().all(|r| roles.contains(r)), \"manifest missing a required role\");","typeGuard":null,"tryCatchPattern":"match validate_manifest(&config) {\n    Err(e) if e.to_string().contains(\"missing a required role\") => {\n        eprintln!(\"add contract entries for all required roles: {e}\");\n    }\n    Err(e) => return Err(e),\n    Ok(v) => v,\n}","preventionTips":["Use a manifest template/checklist that always emits all six required roles","Generate manifests from deployment state, never by deleting entries from a working manifest","Diff each new manifest's role set against the previous accepted one in CI"],"tags":["validation","manifest","config"],"backgroundTag":"missing-required-config-field","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"}