nautechsystems/nautilus_trader · error

Binance v2 does not support instrument filter_callable {filt

Error message

Binance v2 does not support instrument filter_callable {filter_callable:?}; the legacy Binance provider never applied callable filters

What it means

BinanceDataClientConfig.validate rejects the instrument_provider's filter_callable option. The v2 Binance adapter is written in Rust and cannot safely execute arbitrary Python callables while loading instruments, and the legacy provider never actually applied such filters anyway, so the config fails validation rather than silently ignoring the filter.

Source

Thrown at crates/adapters/binance/src/config.rs:88

        Self::builder().build()
    }
}

impl BinanceInstrumentProviderConfig {
    /// Validates instrument loading configuration.
    ///
    /// # Errors
    ///
    /// Returns an error for malformed IDs, unsupported filters, or a legacy
    /// callable filter that Binance v2 cannot execute safely.
    pub fn validate(&self, product_type: BinanceProductType) -> anyhow::Result<()> {
        if let Some(filter_callable) = self
            .filter_callable
            .as_deref()
            .map(str::trim)
            .filter(|value| !value.is_empty())
        {
            anyhow::bail!(
                "Binance v2 does not support instrument filter_callable {filter_callable:?}; \
                 the legacy Binance provider never applied callable filters"
            );
        }

        if let Some(load_ids) = &self.load_ids {
            for raw in load_ids {
                let instrument_id = InstrumentId::from_str(raw)
                    .map_err(|e| anyhow::anyhow!("invalid Binance load_ids value {raw:?}: {e}"))?;
                anyhow::ensure!(
                    instrument_id.venue.as_str() == "BINANCE",
                    "Binance load_ids value {raw:?} must use venue BINANCE"
                );
            }
        }

        for (key, value) in &self.filters {
            let supported = matches!(key.as_str(), "symbols" | "bases" | "quotes")

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Remove filter_callable from the instrument provider config entirely.
  2. Express the filter declaratively with the supported keys: filters={'symbols': [...]} , {'bases': [...]} or {'quotes': [...]}, or use load_ids=['BTCUSDT.BINANCE', ...].
  3. If you need predicate-style filtering, load a superset via filters and drop unwanted instruments in your strategy after they arrive in the cache.

Example fix

# before
config = BinanceDataClientConfig(
    instrument_provider=BinanceFuturesInstrumentProviderConfig(
        filter_callable=lambda i: i.base == 'USDT',
    ),
)

# after
config = BinanceDataClientConfig(
    instrument_provider=BinanceFuturesInstrumentProviderConfig(
        filters={'quotes': ['USDT']},
    ),
)
Defensive patterns

Strategy: validation

Validate before calling

cfg = BinanceDataClientConfig(
    instrument_provider=BinanceFuturesInstrumentProviderConfig(
        load_ids=['BTCUSDT.BINANCE'],
        filters={'quotes': ['USDT']},
    ),
)
cfg.validate()  # fails fast if filter_callable or a bad filter slipped in

Try / catch

try:
    cfg.validate()
except Exception as e:
    raise SystemExit(f'Binance config rejected at startup: {e}')

Prevention

When it happens

Trigger: Setting BinanceFuturesInstrumentProviderConfig(filter_callable=my_fn) (or the equivalent dict/kwargs) on the Binance v2 instrument provider config, then calling config.validate() (which the factory runs automatically on client creation).

Common situations: Migrating a config from the legacy Python Binance adapter or BinanceDataClientConfig snippets found in older docs/blog posts; copy-pasting a provider config that filters instruments with a lambda; attempting to narrow a huge universe (thousands of symbols) with a custom predicate.

Related errors


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