nautechsystems/nautilus_trader · error · anyhow::Error
cannot subscribe L1_MBP and L2_MBP for the same Binance Spot
Error message
cannot subscribe L1_MBP and L2_MBP for the same Binance Spot instrument
What it means
The Spot adapter keeps L1 (bookTicker) and L2 (depth stream) book subscriptions in separate maps per instrument; subscribing top-of-book while an L2 book subscription already exists for the same instrument would produce conflicting/mixed book semantics, so the L1 request is rejected.
Source
Thrown at crates/adapters/binance/src/spot/data.rs:1820
}
fn subscribe_instruments(&mut self, _cmd: SubscribeInstruments) -> anyhow::Result<()> {
log::debug!("subscribe_instruments: Binance instruments are fetched via HTTP on connect");
Ok(())
}
fn subscribe_instrument(&mut self, _cmd: SubscribeInstrument) -> anyhow::Result<()> {
log::debug!("subscribe_instrument: Binance instruments are fetched via HTTP on connect");
Ok(())
}
fn subscribe_book_deltas(&mut self, cmd: SubscribeBookDeltas) -> anyhow::Result<()> {
if cmd.book_type == BookType::L1_MBP {
anyhow::ensure!(
cmd.depth.is_none_or(|depth| depth.get() == 1),
"Binance Spot L1_MBP supports depth 1 only"
);
anyhow::ensure!(
!self.book_subscriptions.contains_key(&cmd.instrument_id),
"cannot subscribe L1_MBP and L2_MBP for the same Binance Spot instrument"
);
self.l1_book_subscriptions.rcu(|subscriptions| {
*subscriptions.entry(cmd.instrument_id).or_insert(0) += 1;
});
self.subscribe_top_of_book(cmd.instrument_id);
return Ok(());
}
if cmd.book_type != BookType::L2_MBP {
anyhow::bail!("Binance Spot supports L1_MBP and L2_MBP order book subscriptions");
}
anyhow::ensure!(
!self.l1_book_subscriptions.contains_key(&cmd.instrument_id),
"cannot subscribe L1_MBP and L2_MBP for the same Binance Spot instrument"
);
View on GitHub (pinned to a4b06ed870)
Solutions
- Unsubscribe the existing L2 book-deltas subscription for that instrument before adding the L1 subscription
- Standardize on one book type per instrument across all strategies; if both views are needed, derive the top of book from the L2 book instead of subscribing L1
Example fix
# before client.subscribe_book_deltas(instrument_id, BookType.L2_MBP, depth=None) client.subscribe_book_deltas(instrument_id, BookType.L1_MBP) # errors: conflict # after client.unsubscribe_book_deltas(instrument_id) # drop L2 first client.subscribe_book_deltas(instrument_id, BookType.L1_MBP)
Defensive patterns
Strategy: validation
Validate before calling
# Track which book type is subscribed per instrument before issuing requests
active: dict[InstrumentId, BookType] = {}
def can_subscribe_l1(instrument_id) -> bool:
return active.get(instrument_id) is not BookType.L2_MBP
assert can_subscribe_l1(instrument_id), "L2 already subscribed for this instrument" Prevention
- Maintain one book type per instrument across all modules
- Derive the top of book from the L2 book instead of dual-subscribing
- Unsubscribe before switching book types at runtime
When it happens
Trigger: subscribe_book_deltas with L1_MBP for an instrument already present in book_subscriptions (an active L2 book subscription).
Common situations: One component of a stack subscribes L2 depth while another (e.g. a quoting or spread module) subscribes L1 for the same symbol; dynamic reconfiguration at runtime without unsubscribing first.
Related errors
- cannot subscribe L1_MBP and L2_MBP for the same Binance Futu
- Binance Spot L1_MBP supports depth 1 only
- Binance Spot supports L1_MBP and L2_MBP order book subscript
- Binance Spot order-book depth must be between 1 and 5000
- Symbol '{}' is not trading (status: {})
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/93635d61befbbc42.
Report an issue: GitHub.