{"record":{"id":"e52be84ba590f7e5","repo":"nautechsystems/nautilus_trader","slug":"invalid-derive-expired-filter-e","errorCode":null,"errorMessage":"invalid Derive `expired` filter: {e}","messagePattern":"invalid Derive `expired` filter: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/providers.rs","lineNumber":306,"sourceCode":"    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}\"))\n        .map(|value| value.unwrap_or(default_expired))\n}\n\nfn split_currencies(value: &str) -> Vec<String> {\n    normalize_currencies(value.split(',').map(ToOwned::to_owned).collect())\n}\n\nfn normalize_currencies(currencies: Vec<String>) -> Vec<String> {\n    let mut currencies: Vec<_> = currencies\n        .into_iter()\n        .map(|currency| currency.trim().to_string())\n        .filter(|currency| !currency.is_empty())\n        .collect();\n    currencies.sort();\n    currencies.dedup();\n    currencies\n}\n","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/providers.rs#L288-L324","documentation":"The `expired` load filter for DeriveInstrumentProvider must parse as a Rust bool (true/false). resolve_expired_filter parses the filter string and wraps any parse failure in this error. Lowercase `true`/`false` are valid; other spellings are not.","triggerScenarios":"Passing filters like {\"expired\": \"True\"}, {\"expired\": \"1\"}, or {\"expired\": \"yes\"} to load_ids/load_all — str::parse::<bool>() only accepts \"true\" or \"false\".","commonSituations":"Using Python-style booleans (`True`) in a string filter map; numeric flags from config files; copy-pasted filter values from other adapters that accept 0/1.","solutions":["Use exactly \"true\" or \"false\" (lowercase) for the expired filter","Normalize the filter value with .to_lowercase() before passing it","Convert numeric/bool config values to canonical bool strings at config load time"],"exampleFix":"// before\nfilters.insert(\"expired\".into(), \"True\".into());\n// after\nfilters.insert(\"expired\".into(), \"true\".into());","handlingStrategy":"validation","validationCode":"let expired = value.to_lowercase();\nassert!(expired == \"true\" || expired == \"false\", \"expired filter must be 'true' or 'false', got {value}\");","typeGuard":"fn parse_expired(v: &str) -> Option<bool> { match v.to_lowercase().as_str() { \"true\" => Some(true), \"false\" => Some(false), _ => None } }","tryCatchPattern":"match provider.load_ids(Some(&filters)).await { Err(e) if e.to_string().contains(\"invalid Derive `expired` filter\") => fix_and_retry(filters), r => r }","preventionTips":["Normalize boolean filter strings to lowercase before passing to adapters","Avoid 0/1 or Python-style True/False in string filter maps","Centralize filter construction in a typed helper that produces canonical bool strings"],"tags":["rust","adapter","filters","parsing"],"backgroundTag":"invalid-argument-format","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"}