{"record":{"id":"9403a29f9b94b07f","repo":"nautechsystems/nautilus_trader","slug":"provider-failure-domains-must-contain-nonempty-opa","errorCode":null,"errorMessage":"Provider failure domains must contain nonempty opaque IDs","messagePattern":"Provider failure domains must contain nonempty opaque IDs","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/verification.rs","lineNumber":1442,"sourceCode":"                .call_edges\n                .iter()\n                .any(|edge| edge.purpose == purpose),\n            \"Deployment manifest is missing a swap call graph\"\n        );\n    }\n    Ok(())\n}\n\nfn validate_identity(identity: &BlockchainProviderIdentity) -> anyhow::Result<()> {\n    anyhow::ensure!(\n        !identity.provider_id.trim().is_empty(),\n        \"Provider ID is required\"\n    );\n    anyhow::ensure!(\n        !identity.operator_id.trim().is_empty(),\n        \"Provider operator ID is required\"\n    );\n    anyhow::ensure!(\n        !identity.failure_domain_ids.is_empty()\n            && identity\n                .failure_domain_ids\n                .iter()\n                .all(|domain| !domain.trim().is_empty()),\n        \"Provider failure domains must contain nonempty opaque IDs\"\n    );\n    ensure_distinct(\n        identity.failure_domain_ids.iter().map(String::as_str),\n        \"failure-domain IDs within one provider\",\n    )\n}\n\nfn ensure_distinct<'a>(\n    values: impl IntoIterator<Item = &'a str>,\n    description: &str,\n) -> anyhow::Result<()> {\n    let values = values.into_iter().collect::<Vec<_>>();","sourceCodeStart":1424,"sourceCodeEnd":1460,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/verification.rs#L1424-L1460","documentation":"This error is raised during provider identity validation in the blockchain RPC verification subsystem. A provider supplies a list of failure-domain identifiers used to model geographic/infrastructure independence for decentralized verification quorums; the library requires the list to be nonempty and every ID to be a nonempty, non-whitespace opaque string. If any of these conditions fails, identity registration is rejected with this anyhow::ensure! error.","triggerScenarios":"Calling the provider-identity validation path (verification.rs:~1442) with an identity whose failure_domain_ids vec is empty, or whose list contains an empty string, all-whitespace string, or an untrimmed value like \" us-east \".","commonSituations":"Config files for RPC providers missing the failure_domains key (deserialized as empty vec); YAML/JSON entries with blank strings ('\"\"' or '   '); hand-written provider config where the operator assumed optional domains; trimming logic upstream that strips values but not list entries.","solutions":["Populate identity.failure_domain_ids with at least one nonempty domain ID before validation","Trim each ID and filter out blank entries when building the identity from config","Validate the provider config at load time so empty/blank domain lists fail early with a clearer message","Ensure IDs are pre-trimmed so trim() equals the value and no whitespace-only entries slip through"],"exampleFix":"// before\nlet identity = ProviderIdentity {\n    failure_domain_ids: vec![],\n    ..identity\n};\n// after\nlet identity = ProviderIdentity {\n    failure_domain_ids: vec![\"us-east-1\".to_string(), \"eu-central-1\".to_string()],\n    ..identity\n};","handlingStrategy":"validation","validationCode":"let domains: Vec<&str> = identity.failure_domain_ids.iter().map(|s| s.as_str()).collect();\nif domains.is_empty() || domains.iter().any(|d| d.trim().is_empty()) {\n    return Err(\"provider failure_domain_ids must be a nonempty list of nonempty, trimmed IDs\");\n}","typeGuard":"fn has_valid_failure_domains(identity: &ProviderIdentity) -> bool {\n    !identity.failure_domain_ids.is_empty()\n        && identity.failure_domain_ids.iter().all(|d| !d.trim().is_empty())\n}","tryCatchPattern":null,"preventionTips":["Validate provider config at load time, before constructing identities","Trim and filter domain IDs when parsing config files","Require failure_domains as a mandatory config key rather than defaulting to empty","Add a schema check that rejects blank strings in list fields"],"tags":["validation","config","blockchain"],"backgroundTag":"empty-required-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"}