nautechsystems/nautilus_trader · error
DeriveInstrumentProvider requires at least one currency
Error message
DeriveInstrumentProvider requires at least one currency
What it means
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.
Source
Thrown at crates/adapters/derive/src/providers.rs:288
}
}
fn resolve_load_filters(
default_currencies: &[String],
default_expired: bool,
filters: Option<&HashMap<String, String>>,
) -> anyhow::Result<(Vec<String>, bool)> {
let currencies = filters
.and_then(|map| {
map.get("currency")
.map(|currency| vec![currency.trim().to_string()])
.or_else(|| map.get("currencies").map(|value| split_currencies(value)))
})
.unwrap_or_else(|| default_currencies.to_vec());
let currencies = normalize_currencies(currencies);
anyhow::ensure!(
!currencies.is_empty(),
"DeriveInstrumentProvider requires at least one currency",
);
let expired = resolve_expired_filter(default_expired, filters)?;
Ok((currencies, expired))
}
fn resolve_expired_filter(
default_expired: bool,
filters: Option<&HashMap<String, String>>,
) -> anyhow::Result<bool> {
filters
.and_then(|map| map.get("expired"))
.map(|value| value.parse::<bool>())
.transpose()
.map_err(|e| anyhow::anyhow!("invalid Derive `expired` filter: {e}"))View on GitHub (pinned to 18893faf8b)
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
Example fix
// before
let filters = HashMap::from([("currencies".to_string(), "".to_string())]);
provider.load_all(Some(&filters)).await?;
// after
let filters = HashMap::from([("currencies".to_string(), "ETH".to_string())]);
provider.load_all(Some(&filters)).await?; Defensive patterns
Strategy: validation
Validate before calling
let currencies: Vec<_> = currencies.split(',').map(str::trim).filter(|s| !s.is_empty()).collect();
assert!(!currencies.is_empty(), "at least one currency required for Derive instruments"); Try / catch
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 } Prevention
- 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
When it happens
Trigger: Calling load_all (or provider load) with filters whose `underlying`/`currencies` entries normalize to an empty vector, and no non-empty default_currencies supplied.
Common situations: 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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Invalid config type for DeriveExecutionClientFactory. Expect
- Invalid config type for LighterExecutionClientFactory. Expec
- Invalid config type for AxExecutionClientFactory. Expected A
- instrument update lock poisoned
- Invalid factory address for DEX {name} on chain {chain} for
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/32b5af7d419e0691.
Report an issue: GitHub.