{"record":{"id":"df1a7898f2bb7e63","repo":"nautechsystems/nautilus_trader","slug":"binance-instrument-filter-name-must-be-a-non-e","errorCode":null,"errorMessage":"Binance instrument filter {name:?} must be a non-empty string or array of strings","messagePattern":"Binance instrument filter (.+?) must be a non-empty string or array of strings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/config.rs","lineNumber":135,"sourceCode":"        }\n\n        Ok(())\n    }\n}\n\nfn validate_filter_strings(name: &str, value: &serde_json::Value) -> anyhow::Result<()> {\n    let valid = match value {\n        serde_json::Value::String(value) => !value.trim().is_empty(),\n        serde_json::Value::Array(values) => {\n            !values.is_empty()\n                && values\n                    .iter()\n                    .all(|value| value.as_str().is_some_and(|value| !value.trim().is_empty()))\n        }\n        _ => false,\n    };\n\n    anyhow::ensure!(\n        valid,\n        \"Binance instrument filter {name:?} must be a non-empty string or array of strings\"\n    );\n    Ok(())\n}\n\n/// Spot market-data transport mode.\n#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]\n#[cfg_attr(\n    feature = \"python\",\n    pyo3::pyclass(module = \"nautilus_trader.adapters.binance\", eq, from_py_object)\n)]\n#[cfg_attr(\n    feature = \"python\",\n    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = \"nautilus_trader.adapters.binance\")\n)]\npub enum BinanceSpotMarketDataMode {\n    #[default]","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/binance/src/config.rs#L117-L153","documentation":"validate_filter_strings requires each instrument filter value to be a single non-empty string, or a non-empty JSON array whose elements are all non-empty strings. Numbers, booleans, objects, null, an empty array, or whitespace-only strings all fail this check before the provider starts.","triggerScenarios":"Setting filters={'bases': ['BTC', 42]} (mixed types), filters={'quotes': 'USDT '.trim() is fine but '  ' is not}, filters={'symbols': []} (empty array), or filters={'bases': {'m': 'main'}} (object) in the instrument provider config; then config.validate() at client creation rejects it.","commonSituations":"Generating filter lists from YAML/JSON config files where values deserialize as numbers (symbol '1100' as int); environment-variable-driven configs that yield empty strings; a typo'd nested dict instead of a flat list.","solutions":["Make every filter value a non-empty string or a list of non-empty strings, e.g. filters={'bases': ['BTC', 'ETH']} or filters={'quotes': 'USDT'}.","Sanitize programmatic values: [str(v).strip() for v in values if str(v).strip()].","Validate the config immediately after construction so the error names the offending filter key early."],"exampleFix":"# before (int elements / empty values)\nfilters={'symbols': [1100, 'BTCUSDT', '']}\n\n# after\nfilters={'symbols': ['1100ETH', 'BTCUSDT']}","handlingStrategy":"validation","validationCode":"def clean_filter_values(values):\n    if isinstance(values, str):\n        values = [values]\n    cleaned = [str(v).strip() for v in values if str(v).strip()]\n    assert cleaned, 'filter must have at least one non-empty string'\n    return cleaned\n\ncfg.filters = {k: clean_filter_values(v) for k, v in cfg.filters.items()}","typeGuard":"def is_valid_filter_value(v) -> bool:\n    if isinstance(v, str):\n        return bool(v.strip())\n    if isinstance(v, list):\n        return bool(v) and all(isinstance(x, str) and x.strip() for x in v)\n    return False","tryCatchPattern":null,"preventionTips":["Quote values loaded from YAML/JSON so symbol-like numbers stay strings.","Strip and drop empty strings when building filter lists programmatically.","Never use nested dicts as filter values."],"tags":["binance","config","filters","json-types","validation"],"backgroundTag":"config-validation-failed","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}