nautechsystems/nautilus_trader · error · anyhow::Error
No order book returned from OKX
Error message
No order book returned from OKX
What it means
Response guard in the OKX HTTP client's order book fetch: the API returned an empty list of books, so no snapshot exists for the requested instrument/depth and the call fails instead of returning an empty book.
Source
Thrown at crates/adapters/okx/src/http/client.rs:2912
) -> anyhow::Result<OrderBook> {
let inst = self.instrument_from_cache_by_id(instrument_id)?;
let price_precision = inst.price_precision();
let size_precision = inst.size_precision();
let params = GetOrderBookParams {
inst_id: instrument_id.symbol.to_string(),
sz: depth,
};
let resp = self
.inner
.get_order_book(params)
.await
.map_err(|e| anyhow::anyhow!(e))?;
let snapshot = resp
.first()
.ok_or_else(|| anyhow::anyhow!("No order book returned from OKX"))?;
let ts_event = UnixNanos::from(snapshot.ts * NANOSECONDS_IN_MILLISECOND);
let mut book = OrderBook::new(instrument_id, BookType::L2_MBP);
for (i, level) in snapshot.bids.iter().enumerate() {
let price = parse_price(&level.0, price_precision)?;
let size = parse_quantity(&level.1, size_precision)?;
let order = BookOrder::new(OrderSide::Buy, price, size, i as u64);
book.add(order, 0, i as u64, ts_event);
}
let bids_len = snapshot.bids.len();
for (i, level) in snapshot.asks.iter().enumerate() {
let price = parse_price(&level.0, price_precision)?;
let size = parse_quantity(&level.1, size_precision)?;
let order = BookOrder::new(OrderSide::Sell, price, size, (bids_len + i) as u64);
book.add(order, 0, (bids_len + i) as u64, ts_event);View on GitHub (pinned to 18893faf8b)
Solutions
- Confirm the inst_id exists via /api/v5/public/instruments before requesting the book.
- Re-sync the instrument cache if the instrument may have been delisted.
- Treat empty responses as a skip-and-retry condition rather than a fatal error.
- Check OKX system status for ongoing incidents.
Example fix
// before
let snapshot = resp.first().ok_or_else(|| anyhow::anyhow!("No order book returned from OKX"))?;
// after
let Some(snapshot) = resp.first() else {
tracing::warn!("OKX book snapshot empty for {instrument_id}; will retry");
return Err(anyhow::anyhow!("empty order book response"));
}; Defensive patterns
Strategy: fallback
Validate before calling
if !okx_instruments_live.contains(inst_id.as_str()) {
return Err(anyhow::anyhow!("instrument {inst_id} not live on OKX"));
} Try / catch
let Some(snapshot) = resp.first() else {
tracing::warn!("empty OKX book for {instrument_id}");
return Err(anyhow::anyhow!("empty book response; retry later"));
}; Prevention
- Re-check the instrument cache for delisted instruments on this error.
- Retry the initial snapshot once before giving up.
- Monitor OKX system status for data gaps.
When it happens
Trigger: OKX responds with data: [] for get_order_book — typically an unknown/delisted instId or a race where the instrument was just suspended/delisted mid-request.
Common situations: Requesting a snapshot for an instrument removed from OKX, a typo'd or mis-derived inst_id, or exchange-side data gaps during incidents/maintenance.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- No index price returned from OKX
- No RPI order book returned from OKX
- No usable instruments for {instrument_type:?}, cannot initia
- No usable instruments for {instrument_type:?} family {family
- No instruments loaded for configured types {instrument_types
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e4e984310ebc0c96.
Report an issue: GitHub.