nautechsystems/nautilus_trader · error

Invalid depth {depth} for Binance Futures order book. Valid

Error message

Invalid depth {depth} for Binance Futures order book. Valid values: {BINANCE_BOOK_DEPTHS:?}

What it means

For L2_MBP subscriptions the requested depth must be one of `BINANCE_BOOK_DEPTHS = [5, 10, 20, 50, 100, 500, 1000]` (crates/adapters/binance/src/common/consts.rs:338); omitting depth defaults to 1000. These are the levels Binance's partial book-depth streams actually offer, so any other value cannot be mapped to a stream and is rejected before the subscription is tracked for reconnect handling.

Source

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

                *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 Futures 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 Futures instrument"
        );

        let instrument_id = cmd.instrument_id;
        let depth = cmd.depth.map_or(1000, |d| d.get() as u32);

        if !BINANCE_BOOK_DEPTHS.contains(&depth) {
            anyhow::bail!(
                "Invalid depth {depth} for Binance Futures order book. \
                Valid values: {BINANCE_BOOK_DEPTHS:?}"
            );
        }

        // Track subscription for reconnect handling
        self.book_subscriptions.insert(instrument_id, depth);

        // Bump epoch to invalidate any in-flight snapshot from a prior subscription
        let epoch = {
            let mut guard = self.book_epoch.write().expect(MUTEX_POISONED);
            *guard = guard.wrapping_add(1);
            *guard
        };

        // Start buffering deltas for this instrument
        self.book_buffers
            .insert(instrument_id, BookBuffer::new(epoch));

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Pick a depth from [5, 10, 20, 50, 100, 500, 1000]
  2. Omit the depth argument entirely to get the default 1000-level book
  3. If you need a custom display depth (e.g. 25), subscribe the next larger valid depth (50) and trim client-side

Example fix

# before
actor.subscribe_order_book_deltas(instrument_id, book_type=BookType.L2_MBP, depth=250)

# after
actor.subscribe_order_book_deltas(instrument_id, book_type=BookType.L2_MBP, depth=500)
Defensive patterns

Strategy: validation

Validate before calling

BINANCE_FUTURES_BOOK_DEPTHS = {5, 10, 20, 50, 100, 500, 1000}

def validate_binance_l2_depth(depth) -> int:
    if depth is None:
        return 1000  # adapter default
    if depth not in BINANCE_FUTURES_BOOK_DEPTHS:
        raise ValueError(f'depth {depth} invalid for Binance Futures; valid: {sorted(BINANCE_FUTURES_BOOK_DEPTHS)}')
    return depth

validate_binance_l2_depth(depth)
actor.subscribe_order_book_deltas(instrument_id, book_type=BookType.L2_MBP, depth=depth)

Type guard

BINANCE_FUTURES_BOOK_DEPTHS = {5, 10, 20, 50, 100, 500, 1000}

def is_valid_binance_depth(depth) -> bool:
    return depth in BINANCE_FUTURES_BOOK_DEPTHS

Try / catch

try:
    actor.subscribe_order_book_deltas(instrument_id, book_type=BookType.L2_MBP, depth=depth)
except Exception as e:
    if 'Invalid depth' in str(e) and 'Binance Futures order book' in str(e):
        nearest = min(BINANCE_FUTURES_BOOK_DEPTHS, key=lambda d: abs(d - depth))
        actor.subscribe_order_book_deltas(instrument_id, book_type=BookType.L2_MBP, depth=nearest)
    else:
        raise

Prevention

When it happens

Trigger: `subscribe_book_deltas` with `book_type=BookType.L2_MBP` and depth not in the set — e.g. 25, 250, 200, 300 (depths valid on other venues but not in this adapter's constant list). Depth None is allowed and becomes 1000.

Common situations: Porting configs from Binance spot or other exchanges whose valid depth lists differ; assuming any positive depth is accepted; sharing a generic depth parameter (e.g. 250) across multi-venue strategies.

Related errors


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