nautechsystems/nautilus_trader · error · anyhow::Error
invalid Binance Futures order-book depth {depth}; valid valu
Error message
invalid Binance Futures order-book depth {depth}; valid values are {BINANCE_BOOK_DEPTHS:?} What it means
Thrown by request_book_snapshot on the Binance Futures data client when the requested order-book depth is not one of the exchange-supported levels. Binance futures /fapi/v1/depth and /dapi/v1/depth accept only the depths mirrored in BINANCE_BOOK_DEPTHS = [5, 10, 20, 50, 100, 500, 1000] (crates/adapters/binance/src/common/consts.rs:338). When request.depth is None the client defaults to 1000, which is always accepted.
Source
Thrown at crates/adapters/binance/src/futures/data.rs:3044
end_nanos,
clock.get_time_ns(),
params,
));
if let Err(e) = sender.send(DataEvent::Response(response)) {
log::error!("Failed to send bars response: {e}");
}
}
Err(e) => log::error!("Bar request failed: {e:?}"),
}
});
Ok(())
}
fn request_book_snapshot(&self, request: RequestBookSnapshot) -> anyhow::Result<()> {
let depth = request.depth.map_or(1000, |value| value.get() as u32);
anyhow::ensure!(
BINANCE_BOOK_DEPTHS.contains(&depth),
"invalid Binance Futures order-book depth {depth}; valid values are {BINANCE_BOOK_DEPTHS:?}"
);
let http = self.http_client.clone();
let sender = self.data_sender.clone();
let instrument_id = request.instrument_id;
let request_id = request.request_id;
let client_id = request.client_id.unwrap_or(self.client_id);
let params = request.params;
let clock = self.clock;
get_runtime().spawn(async move {
match http.request_book_snapshot(instrument_id, Some(depth)).await {
Ok(book) => {
let response = DataResponse::Book(BookResponse::new(
request_id,
client_id,
instrument_id,View on GitHub (pinned to a4b06ed870)
Solutions
- Set depth to one of 5, 10, 20, 50, 100, 500, or 1000
- Omit depth (pass None) to use the default of 1000
- Validate any user-configured depth against the allowed list before submitting the snapshot request
Example fix
// before let request = RequestBookSnapshot::new(instrument_id, client_id, request_id, Some(200.non_zero()?)); // after let request = RequestBookSnapshot::new(instrument_id, client_id, request_id, Some(500.non_zero()?));
Defensive patterns
Strategy: validation
Validate before calling
const BINANCE_BOOK_DEPTHS: [u32; 7] = [5, 10, 20, 50, 100, 500, 1000];
let depth = requested_depth.unwrap_or(1000);
assert!(BINANCE_BOOK_DEPTHS.contains(&depth), "depth must be one of {BINANCE_BOOK_DEPTHS:?}");
// then send RequestBookSnapshot Type guard
fn is_valid_binance_depth(depth: u32) -> bool {
[5, 10, 20, 50, 100, 500, 1000].contains(&depth)
} Prevention
- Whitelist user-supplied depth values against the venue's documented levels at config load
- Default to None (1000) rather than inventing a depth
- Remember spot and futures depth lists can differ — validate per adapter
When it happens
Trigger: Sending a RequestBookSnapshot whose depth field holds an unsupported value such as 25, 200, or 2000 — e.g. depth copied from another venue's config or computed dynamically from user settings.
Common situations: Reusing a Bybit/OKX depth setting (those venues allow 25/200) on the Binance futures adapter; passing a raw user-supplied 'limit' straight into the request without whitelisting.
Related errors
- Binance Futures L1_MBP supports depth 1 only
- Invalid depth {depth} for Binance Futures order book. Valid
- Binance historical bars require time aggregation
- Binance Futures ticker custom data requires BINANCE venue in
- BinanceFuturesExecutionClient requires UsdM or CoinM product
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/3dd5d8976dda2259.
Report an issue: GitHub.