{"record":{"id":"32b5af7d419e0691","repo":"nautechsystems/nautilus_trader","slug":"deriveinstrumentprovider-requires-at-least-one-cur","errorCode":null,"errorMessage":"DeriveInstrumentProvider requires at least one currency","messagePattern":"DeriveInstrumentProvider requires at least one currency","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/providers.rs","lineNumber":288,"sourceCode":"    }\n}\n\nfn resolve_load_filters(\n    default_currencies: &[String],\n    default_expired: bool,\n    filters: Option<&HashMap<String, String>>,\n) -> anyhow::Result<(Vec<String>, bool)> {\n    let currencies = filters\n        .and_then(|map| {\n            map.get(\"currency\")\n                .map(|currency| vec![currency.trim().to_string()])\n                .or_else(|| map.get(\"currencies\").map(|value| split_currencies(value)))\n        })\n        .unwrap_or_else(|| default_currencies.to_vec());\n\n    let currencies = normalize_currencies(currencies);\n\n    anyhow::ensure!(\n        !currencies.is_empty(),\n        \"DeriveInstrumentProvider requires at least one currency\",\n    );\n\n    let expired = resolve_expired_filter(default_expired, filters)?;\n\n    Ok((currencies, expired))\n}\n\nfn resolve_expired_filter(\n    default_expired: bool,\n    filters: Option<&HashMap<String, String>>,\n) -> anyhow::Result<bool> {\n    filters\n        .and_then(|map| map.get(\"expired\"))\n        .map(|value| value.parse::<bool>())\n        .transpose()\n        .map_err(|e| anyhow::anyhow!(\"invalid Derive `expired` filter: {e}\"))","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/providers.rs#L270-L306","documentation":"DeriveInstrumentProvider::resolve_load_filters resolves the currency list from load filters or a default, normalizes it, then requires it to be non-empty. An empty currency set would produce no loadable instruments, so the provider refuses with this ensure! error.","triggerScenarios":"Calling load_all (or provider load) with filters whose `underlying`/`currencies` entries normalize to an empty vector, and no non-empty default_currencies supplied.","commonSituations":"Passing `currencies: \"\"` or `underlying: \"\"` in a filters HashMap; an empty currencies vec configured in a client config; whitespace-only filter values stripped by normalize_currencies.","solutions":["Provide at least one currency in the load filters (e.g. \"currencies\": \"ETH\")","Set a non-empty default_currencies in the provider/client config","Remove the empty filter key so the default currencies are used"],"exampleFix":"// before\nlet filters = HashMap::from([(\"currencies\".to_string(), \"\".to_string())]);\nprovider.load_all(Some(&filters)).await?;\n// after\nlet filters = HashMap::from([(\"currencies\".to_string(), \"ETH\".to_string())]);\nprovider.load_all(Some(&filters)).await?;","handlingStrategy":"validation","validationCode":"let currencies: Vec<_> = currencies.split(',').map(str::trim).filter(|s| !s.is_empty()).collect();\nassert!(!currencies.is_empty(), \"at least one currency required for Derive instruments\");","typeGuard":null,"tryCatchPattern":"match provider.load_all(Some(&filters)).await { Err(e) if e.to_string().contains(\"requires at least one currency\") => provider.load_all(None).await, r => r }","preventionTips":["Filter out empty/whitespace currency strings before building the filters map","Always configure a non-empty default_currencies in the Derive client config","Drop filter keys entirely rather than passing empty values"],"tags":["rust","adapter","instruments","config"],"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-14T00:17:10.932Z"}