nautechsystems/nautilus_trader · error
Slice length != 10
Error message
Slice length != 10
What it means
orderbook_depth10_new builds fixed-size [BookOrderFfi; 10] arrays from raw pointers by converting a slice of DEPTH10_LEN via try_into().expect("Slice length != 10"). Although the slice is created with from_raw_parts(..., DEPTH10_LEN) and therefore should always be length 10, if the conversion is invoked with a differently sized buffer/layout mismatch this expect panics. It is an internal invariant check guarding the fixed-depth-10 FFI contract.
Source
Thrown at crates/model/src/ffi/data/depth.rs:108
asks_ptr: *const BookOrderFfi,
bid_counts_ptr: *const u32,
ask_counts_ptr: *const u32,
flags: u8,
sequence: u64,
ts_event: UnixNanos,
ts_init: UnixNanos,
) -> OrderBookDepth10Ffi {
abort_on_panic(|| {
// SAFETY: Null checks run before slice construction. The caller still
// guarantees each pointer refers to `DEPTH10_LEN` initialized elements.
assert!(!bids_ptr.is_null());
assert!(!asks_ptr.is_null());
assert!(!bid_counts_ptr.is_null());
assert!(!ask_counts_ptr.is_null());
let bids_slice = unsafe { std::slice::from_raw_parts(bids_ptr, DEPTH10_LEN) };
let asks_slice = unsafe { std::slice::from_raw_parts(asks_ptr, DEPTH10_LEN) };
let bids: [BookOrderFfi; DEPTH10_LEN] = bids_slice.try_into().expect("Slice length != 10");
let asks: [BookOrderFfi; DEPTH10_LEN] = asks_slice.try_into().expect("Slice length != 10");
let bid_counts_slice = unsafe { std::slice::from_raw_parts(bid_counts_ptr, DEPTH10_LEN) };
let ask_counts_slice = unsafe { std::slice::from_raw_parts(ask_counts_ptr, DEPTH10_LEN) };
let bid_counts: [u32; DEPTH10_LEN] =
bid_counts_slice.try_into().expect("Slice length != 10");
let ask_counts: [u32; DEPTH10_LEN] =
ask_counts_slice.try_into().expect("Slice length != 10");
OrderBookDepth10::new(
instrument_id,
bids.map(Into::into),
asks.map(Into::into),
bid_counts,
ask_counts,
flags,
sequence,
ts_event,View on GitHub (pinned to 18893faf8b)
Solutions
- Allocate exactly 10 elements of the exact BookOrderFfi layout for bids and asks before the call.
- Rebuild bindings against the current model crate so BookOrderFfi size/alignment match on both sides.
- Check for compiler warnings about type layout changes after upgrading nautilus; pin compatible versions.
- If you maintain the FFI wrapper, assert the ctypes.sizeof/length equals the Rust-side size and 10 elements before calling.
Example fix
// before (ctypes) bids = (BookOrderFfi * depth) (*orders) # depth may not be 10 // after assert depth == 10, "Depth10 requires exactly 10 orders per side" bids = (BookOrderFfi * 10)(*orders[:10])
Defensive patterns
Strategy: validation
Validate before calling
# Python caller assert len(bids) == 10 and len(asks) == 10, "Depth10 needs exactly 10 orders per side"
Prevention
- Allocate fixed [T; 10] / (T * 10) buffers for both sides.
- Keep struct layouts (BookOrderFfi) identical on both sides of the FFI boundary.
- Upgrade caller bindings and Rust extension together.
When it happens
Trigger: Calling orderbook_depth10_new with bid/ask pointer buffers that are not exactly 10 contiguous BookOrderFfi elements (undersized allocations, wrong struct packing, or mismatched layout between caller and library).
Common situations: Custom Cython/ctypes bindings that allocate arrays with the wrong element size or count, ABI drift after BookOrderFfi changed, or adapter code reusing depth buffers sized for other depth levels.
Related errors
- Error: No bid orders for best bid price
- 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)
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c3a30e865d607ca8.
Report an issue: GitHub.