nautechsystems/nautilus_trader · error · anyhow::Error

filter {key:?} contains a non-string value

Error message

filter {key:?} contains a non-string value

What it means

Parsing a Binance instrument-loading filter from client config: the filter value must be a JSON string or an array of strings. This error fires when the value is an array but at least one element is not a string (number, bool, null, or object).

Source

Thrown at crates/adapters/binance/src/common/instruments.rs:100

    }
}

fn filter_values(
    config: &BinanceInstrumentProviderConfig,
    key: &str,
) -> anyhow::Result<Option<AHashSet<String>>> {
    let Some(value) = config.filters.get(key) else {
        return Ok(None);
    };

    let values = match value {
        serde_json::Value::String(value) => vec![value.as_str()],
        serde_json::Value::Array(values) => values
            .iter()
            .map(|value| {
                value
                    .as_str()
                    .ok_or_else(|| anyhow::anyhow!("filter {key:?} contains a non-string value"))
            })
            .collect::<anyhow::Result<Vec<_>>>()?,
        _ => anyhow::bail!("filter {key:?} is not a string or array"),
    };

    Ok(Some(
        values
            .into_iter()
            .map(|value| value.trim().to_ascii_uppercase())
            .collect(),
    ))
}

fn matches_filter(values: &Option<AHashSet<String>>, value: &str) -> bool {
    values.as_ref().is_none_or(|values| contains(values, value))
}

fn contains(values: &AHashSet<String>, value: &str) -> bool {

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Quote every entry in the filter array: underlyings: ["6", "11", "BTCUSDT"]
  2. Ensure booleans/nulls/objects never appear in filter arrays
  3. Validate the config JSON shape (all elements strings) before constructing the client

Example fix

# before (YAML)
filter_unders: [6, 11, BTCUSDT]   # 6 and 11 parse as numbers

# after
filter_unders: ["6", "11", "BTCUSDT"]
Defensive patterns

Strategy: validation

Validate before calling

fn filter_values_valid(v: &serde_json::Value) -> bool {
    match v {
        serde_json::Value::String(_) => true,
        serde_json::Value::Array(items) => items.iter().all(|i| i.is_string()),
        _ => false,
    }
}
// run over every entry in config.filters before constructing the client

Type guard

fn is_string_or_string_array(v: &serde_json::Value) -> bool {
    match v {
        serde_json::Value::String(_) => true,
        serde_json::Value::Array(items) => items.iter().all(|i| i.is_string()),
        _ => false,
    }
}

Try / catch

if !config.filters.iter().all(|(k, v)| is_string_or_string_array(v)) {
    anyhow::bail!("Binance filter config malformed - all values must be strings or arrays of strings");
}

Prevention

When it happens

Trigger: Config such as {"filter_unders": [123, "BTCUSDT"]} or YAML where an unquoted numeric/boolean entry parses as a non-string JSON scalar inside the filter array.

Common situations: YAML configs with unquoted numbers (e.g. underlying codes like 6 or 11) or booleans/nulls inside filter lists; machine-generated config from a schema-less source.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/2bbdd127e45c54c4. Report an issue: GitHub.