{"record":{"id":"d1a804fe94c8bbe3","repo":"nautechsystems/nautilus_trader","slug":"binance-liquidation-custom-data-requires-binance-v","errorCode":null,"errorMessage":"Binance liquidation custom data requires BINANCE venue instrument, received {instrument_id}","messagePattern":"Binance liquidation custom data requires BINANCE venue instrument, received (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/futures/data.rs","lineNumber":1844,"sourceCode":"                        ws.subscribe(vec![stream])\n                            .await\n                            .context(\"mark price custom subscription\")\n                    },\n                    \"mark price custom subscription\",\n                );\n            }\n            return Ok(());\n        }\n\n        if data_type != \"BinanceFuturesLiquidation\" {\n            log::warn!(\"Unsupported custom data subscription: {data_type}\");\n            return Ok(());\n        }\n\n        let instrument_id = Self::custom_liquidation_instrument_id(&cmd.data_type)?;\n        if let Some(instrument_id) = instrument_id {\n            if instrument_id.venue != self.venue() {\n                anyhow::bail!(\n                    \"Binance liquidation custom data requires BINANCE venue instrument, received {instrument_id}\"\n                );\n            }\n\n            let should_subscribe = {\n                let prev = self\n                    .force_order_refs\n                    .load()\n                    .get(&instrument_id)\n                    .copied()\n                    .unwrap_or(0);\n                self.force_order_refs.rcu(|m| {\n                    let count = m.entry(instrument_id).or_insert(0);\n                    *count += 1;\n                });\n                prev == 0\n            };\n","sourceCodeStart":1826,"sourceCodeEnd":1862,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/binance/src/futures/data.rs#L1826-L1862","documentation":"For `BinanceFuturesLiquidation` custom-data subscriptions, omitting `instrument_id` metadata is valid (the all-market forceOrder stream is used); supplying one is only valid when its venue is BINANCE. This guard rejects the subscribe before the `force_order_refs` refcounts are touched, so the adapter never opens a liquidation stream keyed to another venue's instrument.","triggerScenarios":"`subscribe_custom_data` with data type name `BinanceFuturesLiquidation` and metadata `{'instrument_id': 'ETHUSDT-PERP.OKX'}` — any successfully parsed InstrumentId whose venue differs from BINANCE. Missing or empty instrument_id metadata does NOT trigger this (it selects the all-market stream).","commonSituations":"Strategy config templating that injects the same instrument string into every venue's client; renaming venues in config and forgetting the liquidation metadata; copy-paste from another adapter's liquidation example.","solutions":["Set the metadata instrument_id to a BINANCE futures instrument, e.g. {'instrument_id': 'ETHUSDT-PERP.BINANCE'}","Or remove the instrument_id key entirely to subscribe to the all-market liquidation stream","Add a venue assertion in your subscription wrapper before calling the Binance client"],"exampleFix":"# before\nmeta = {'instrument_id': 'ETHUSDT-PERP.OKX'}\nactor.subscribe_custom_data(DataType(BinanceFuturesLiquidation, metadata=meta))\n\n# after: per-instrument stream on the right venue\nmeta = {'instrument_id': 'ETHUSDT-PERP.BINANCE'}\nactor.subscribe_custom_data(DataType(BinanceFuturesLiquidation, metadata=meta))\n# or all-market stream: metadata=None / omit instrument_id","handlingStrategy":"validation","validationCode":"def liquidation_metadata(instrument_id=None):\n    if instrument_id is None:\n        return None  # all-market forceOrder stream: no venue constraint\n    if instrument_id.venue.value != 'BINANCE':\n        raise ValueError(f'Binance liquidation stream needs a BINANCE instrument, got {instrument_id}')\n    return {'instrument_id': str(instrument_id)}\n\nactor.subscribe_custom_data(DataType(BinanceFuturesLiquidation, metadata=liquidation_metadata(instrument_id)))","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 'liquidation custom data requires BINANCE venue instrument' in str(e):\n        raise ValueError('Fix the instrument_id venue to BINANCE, or drop the key to use the all-market stream') from e\n    raise","preventionTips":["Remember omitting instrument_id is valid and subscribes the all-market liquidation stream","Use one helper to build liquidation metadata for both subscribe and unsubscribe so venues cannot diverge"],"tags":["binance","futures","liquidation","venue","subscription-validation"],"backgroundTag":"venue-mismatch","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}