nautechsystems/nautilus_trader · error

Futures mark price requires a BINANCE instrument

Error message

Futures mark price requires a BINANCE instrument

What it means

Subscribing to `BinanceFuturesMarkPriceUpdate` custom data requires the parsed `instrument_id` metadata to have a venue equal to the data client's venue (BINANCE). The `ensure!` runs after `required_instrument_id_metadata` parses the metadata but before any refcount bump or stream subscription, so a wrong-venue instrument is rejected up front. Binance mark-price streams only exist for Binance futures instruments.

Source

Thrown at crates/adapters/binance/src/futures/data.rs:1802

    }

    fn is_connected(&self) -> bool {
        self.is_connected.load(Ordering::Relaxed)
    }

    fn is_disconnected(&self) -> bool {
        !self.is_connected()
    }

    fn subscribe(&mut self, cmd: SubscribeCustomData) -> anyhow::Result<()> {
        let data_type = cmd.data_type.type_name();
        if data_type == "BinanceFuturesTicker" {
            return subscribe_ticker(self, &cmd.data_type);
        }

        if data_type == "BinanceFuturesMarkPriceUpdate" {
            let instrument_id = Self::required_instrument_id_metadata(&cmd.data_type)?;
            anyhow::ensure!(
                instrument_id.venue == self.venue(),
                "Futures mark price requires a BINANCE instrument"
            );
            let should_subscribe = {
                let previous = self
                    .mark_price_refs
                    .load()
                    .get(&instrument_id)
                    .copied()
                    .unwrap_or(0);
                self.mark_price_refs
                    .rcu(|refs| *refs.entry(instrument_id).or_insert(0) += 1);
                previous == 0
            };

            if should_subscribe {
                let ws = self.ws_client.clone();
                let stream = format!(

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Use a BINANCE futures instrument id in the metadata, e.g. {'instrument_id': 'BTCUSDT-PERP.BINANCE'}
  2. Route instruments to the adapter matching their venue before subscribing custom data
  3. Validate `instrument_id.venue == 'BINANCE'` in your own code before issuing the subscription

Example fix

# before
meta = {'instrument_id': 'BTCUSDT-PERP.BYBIT'}  # wrong venue
actor.subscribe_custom_data(DataType(BinanceFuturesMarkPriceUpdate, metadata=meta))

# after
meta = {'instrument_id': 'BTCUSDT-PERP.BINANCE'}
actor.subscribe_custom_data(DataType(BinanceFuturesMarkPriceUpdate, metadata=meta))
Defensive patterns

Strategy: validation

Validate before calling

def assert_binance_venue(instrument_id) -> None:
    if instrument_id.venue.value != 'BINANCE':
        raise ValueError(
            f'BinanceFuturesMarkPriceUpdate requires a BINANCE instrument, got {instrument_id}'
        )

assert_binance_venue(instrument_id)
actor.subscribe_custom_data(
    DataType(BinanceFuturesMarkPriceUpdate, metadata={'instrument_id': str(instrument_id)})
)

Type guard

def is_binance_instrument(instrument_id) -> bool:
    return instrument_id.venue.value == 'BINANCE'

Try / catch

try:
    actor.subscribe_custom_data(data_type)
except Exception as e:
    if 'requires a BINANCE instrument' in str(e):
        raise ValueError(f'Route {data_type.metadata["instrument_id"]} to its own venue adapter; BINANCE instruments only here') from e
    raise

Prevention

When it happens

Trigger: `subscribe_custom_data` with data type name `BinanceFuturesMarkPriceUpdate` and metadata `{'instrument_id': 'BTCUSDT-PERP.BYBIT'}` (or any non-BINANCE venue). The instrument_id must parse successfully first; an unparseable string triggers the separate 'invalid instrument_id metadata' error instead.

Common situations: Copy-pasting an instrument string from another adapter's example; multi-venue strategies passing a generic instrument into the Binance client without routing; building metadata from user config without a venue check.

Related errors


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