nautechsystems/nautilus_trader · critical
Error: No bid orders for best bid price
Error message
Error: No bid orders for best bid price
What it means
This Rust panic occurs in the FFI wrapper `orderbook_best_bid_price` when `OrderBook::best_bid_price()` returns None, i.e. the book's bid side contains no orders so there is no best bid price to return. Because the wrapper runs inside `abort_on_panic`, the panic aborts the whole process rather than returning an error to the FFI caller (e.g. Python).
Source
Thrown at crates/model/src/ffi/orderbook/book.rs:261
#[unsafe(no_mangle)]
pub extern "C" fn orderbook_has_bid(book: &mut OrderBook) -> u8 {
u8::from(book.has_bid())
}
#[unsafe(no_mangle)]
pub extern "C" fn orderbook_has_ask(book: &mut OrderBook) -> u8 {
u8::from(book.has_ask())
}
/// # Panics
///
/// Panics if there are no bid orders for best bid price.
#[unsafe(no_mangle)]
#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
pub extern "C" fn orderbook_best_bid_price(book: &mut OrderBook) -> Price {
abort_on_panic(|| {
book.best_bid_price()
.expect("Error: No bid orders for best bid price")
})
}
/// # Panics
///
/// Panics if there are no ask orders for best ask price.
#[unsafe(no_mangle)]
#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
pub extern "C" fn orderbook_best_ask_price(book: &mut OrderBook) -> Price {
abort_on_panic(|| {
book.best_ask_price()
.expect("Error: No ask orders for best ask price")
})
}
/// # Panics
///
/// Panics if there are no bid orders for best bid size.View on GitHub (pinned to 18893faf8b)
Solutions
- Check the book has bids before calling: `book.has_orders()` and `book.best_bid_price()` / `book.get_price(Side.BUY)` availability (or check `book.bids()` is non-empty) in the caller.
- Ensure the book is initialized with an initial snapshot (e.g. `OrderBookDeltas` or quote/trade data) before querying best prices.
- Handle empty-book cases at the strategy level by treating best bid as None and skipping the calculation.
- Verify you are querying the correct instrument_id's book and that the data feed is connected and publishing bid-side data.
Example fix
// before (Python FFI caller)
best_bid = orderbook_best_bid_price(book)
// after
if book_update_count > 0 and has_bid_orders(book):
best_bid = orderbook_best_bid_price(book)
else:
best_bid = None Defensive patterns
Strategy: validation
Validate before calling
def can_get_best_bid(book) -> bool:
return book.has_orders() and book.bids_len() > 0 # or check best bid price availability Type guard
def has_bid_side(book) -> bool:
try:
return len(book.bids()) > 0
except Exception:
return False Prevention
- Never call best-bid getters before the first book update arrives
- Track a book-ready flag set after the initial snapshot is applied
- Treat empty books as an expected state and query optional accessors instead of FFI panicking ones
- Remember FFI panics abort the process — they cannot be caught as exceptions
When it happens
Trigger: Calling the FFI function `orderbook_best_bid_price(book)` on an OrderBook whose bid side is empty: no quotes/trades/depth updates have populated bids, all bids were deleted, or the book was just created/cleared.
Common situations: Querying a book before the first market-data snapshot arrives; a depth feed that only sent ask-side updates; book_l1/book_l3 data cleared by a `clear` call; instrument-specific books for symbols with no bids (illiquid markets).
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
- Error: No ask orders for best ask price
- Error: No bid orders for best bid size
- Error: No ask orders for best ask size
- Error: Unable to calculate `spread` (no bid or ask)
- Error: Unable to calculate `midpoint` (no bid or ask)
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/58deee159048f231.
Report an issue: GitHub.