{"record":{"id":"f03dac056182f10a","repo":"nautechsystems/nautilus_trader","slug":"futures-mark-price-requires-a-binance-instrument","errorCode":null,"errorMessage":"Futures mark price requires a BINANCE instrument","messagePattern":"Futures mark price requires a BINANCE instrument","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/futures/data.rs","lineNumber":1802,"sourceCode":"    }\n\n    fn is_connected(&self) -> bool {\n        self.is_connected.load(Ordering::Relaxed)\n    }\n\n    fn is_disconnected(&self) -> bool {\n        !self.is_connected()\n    }\n\n    fn subscribe(&mut self, cmd: SubscribeCustomData) -> anyhow::Result<()> {\n        let data_type = cmd.data_type.type_name();\n        if data_type == \"BinanceFuturesTicker\" {\n            return subscribe_ticker(self, &cmd.data_type);\n        }\n\n        if data_type == \"BinanceFuturesMarkPriceUpdate\" {\n            let instrument_id = Self::required_instrument_id_metadata(&cmd.data_type)?;\n            anyhow::ensure!(\n                instrument_id.venue == self.venue(),\n                \"Futures mark price requires a BINANCE instrument\"\n            );\n            let should_subscribe = {\n                let previous = self\n                    .mark_price_refs\n                    .load()\n                    .get(&instrument_id)\n                    .copied()\n                    .unwrap_or(0);\n                self.mark_price_refs\n                    .rcu(|refs| *refs.entry(instrument_id).or_insert(0) += 1);\n                previous == 0\n            };\n\n            if should_subscribe {\n                let ws = self.ws_client.clone();\n                let stream = format!(","sourceCodeStart":1784,"sourceCodeEnd":1820,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/binance/src/futures/data.rs#L1784-L1820","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Use a BINANCE futures instrument id in the metadata, e.g. {'instrument_id': 'BTCUSDT-PERP.BINANCE'}","Route instruments to the adapter matching their venue before subscribing custom data","Validate `instrument_id.venue == 'BINANCE'` in your own code before issuing the subscription"],"exampleFix":"# before\nmeta = {'instrument_id': 'BTCUSDT-PERP.BYBIT'}  # wrong venue\nactor.subscribe_custom_data(DataType(BinanceFuturesMarkPriceUpdate, metadata=meta))\n\n# after\nmeta = {'instrument_id': 'BTCUSDT-PERP.BINANCE'}\nactor.subscribe_custom_data(DataType(BinanceFuturesMarkPriceUpdate, metadata=meta))","handlingStrategy":"validation","validationCode":"def assert_binance_venue(instrument_id) -> None:\n    if instrument_id.venue.value != 'BINANCE':\n        raise ValueError(\n            f'BinanceFuturesMarkPriceUpdate requires a BINANCE instrument, got {instrument_id}'\n        )\n\nassert_binance_venue(instrument_id)\nactor.subscribe_custom_data(\n    DataType(BinanceFuturesMarkPriceUpdate, metadata={'instrument_id': str(instrument_id)})\n)","typeGuard":"def is_binance_instrument(instrument_id) -> bool:\n    return instrument_id.venue.value == 'BINANCE'","tryCatchPattern":"try:\n    actor.subscribe_custom_data(data_type)\nexcept Exception as e:\n    if 'requires a BINANCE instrument' in str(e):\n        raise ValueError(f'Route {data_type.metadata[\"instrument_id\"]} to its own venue adapter; BINANCE instruments only here') from e\n    raise","preventionTips":["Derive metadata instrument_id from the same InstrumentId object you trade — never retype the string","In multi-venue strategies, dispatch custom-data subscriptions by instrument venue before calling any adapter"],"tags":["binance","futures","mark-price","venue","subscription-validation"],"backgroundTag":"venue-mismatch","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}