nautechsystems/nautilus_trader · error

invalid Derive `expired` filter: {e}

Error message

invalid Derive `expired` filter: {e}

What it means

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.

Source

Thrown at crates/adapters/derive/src/providers.rs:306

    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}"))
        .map(|value| value.unwrap_or(default_expired))
}

fn split_currencies(value: &str) -> Vec<String> {
    normalize_currencies(value.split(',').map(ToOwned::to_owned).collect())
}

fn normalize_currencies(currencies: Vec<String>) -> Vec<String> {
    let mut currencies: Vec<_> = currencies
        .into_iter()
        .map(|currency| currency.trim().to_string())
        .filter(|currency| !currency.is_empty())
        .collect();
    currencies.sort();
    currencies.dedup();
    currencies
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use exactly "true" or "false" (lowercase) for the expired filter
  2. Normalize the filter value with .to_lowercase() before passing it
  3. Convert numeric/bool config values to canonical bool strings at config load time

Example fix

// before
filters.insert("expired".into(), "True".into());
// after
filters.insert("expired".into(), "true".into());
Defensive patterns

Strategy: validation

Validate before calling

let expired = value.to_lowercase();
assert!(expired == "true" || expired == "false", "expired filter must be 'true' or 'false', got {value}");

Type guard

fn parse_expired(v: &str) -> Option<bool> { match v.to_lowercase().as_str() { "true" => Some(true), "false" => Some(false), _ => None } }

Try / catch

match provider.load_ids(Some(&filters)).await { Err(e) if e.to_string().contains("invalid Derive `expired` filter") => fix_and_retry(filters), r => r }

Prevention

When it happens

Trigger: Passing filters like {"expired": "True"}, {"expired": "1"}, or {"expired": "yes"} to load_ids/load_all — str::parse::<bool>() only accepts "true" or "false".

Common situations: 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.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/e52be84ba590f7e5. Report an issue: GitHub.