nautechsystems/nautilus_trader · critical

invalid `BookType` enum string value, was '{value}'

Error message

invalid `BookType` enum string value, was '{value}'

What it means

`book_type_from_cstr` parses a C string into the Rust `BookType` enum (order book depth types) and panics if the string matches no variant. The library deliberately panics on unknown enum strings, and at the FFI boundary `abort_on_panic` turns that panic into a process abort rather than undefined behavior across the C ABI. Input must exactly equal a canonical `BookType` serialization from `book_type_to_cstr`.

Source

Thrown at crates/model/src/ffi/enums.rs:458

pub extern "C" fn book_type_to_cstr(value: BookType) -> *const c_char {
    str_to_cstr(value.as_ref())
}

/// Returns an enum from a C string.
///
/// # Safety
///
/// Assumes `ptr` is a valid C string pointer.
///
/// # Panics
///
/// Panics if the C string does not correspond to a valid `BookType` variant.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn book_type_from_cstr(ptr: *const c_char) -> BookType {
    abort_on_panic(|| {
        let value = unsafe { cstr_as_str(ptr) };
        BookType::from_str(value)
            .unwrap_or_else(|_| panic!("invalid `BookType` enum string value, was '{value}'"))
    })
}

#[unsafe(no_mangle)]
pub extern "C" fn contingency_type_to_cstr(value: ContingencyTypeOptional) -> *const c_char {
    str_to_cstr(value.as_ref())
}

/// Returns an enum from a C string.
///
/// # Safety
///
/// Assumes `ptr` is a valid C string pointer.
///
/// # Panics
///
/// Panics if the C string does not correspond to a valid `ContingencyTypeOptional` variant.
#[unsafe(no_mangle)]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the exact string and diff against canonical `BookType` variant spellings (see the enum's FromStr impl).
  2. Derive the string from the enum via `book_type_to_cstr` rather than hard-coding.
  3. Normalize case and strip whitespace before the call.
  4. Add an explicit mapping from config/feed vocabulary to `BookType` strings at the boundary.
  5. Validate before the call — invalid input aborts the whole process, not just the request.

Example fix

// before
bt = "L2_BOOK"
book_type_from_cstr(bt.encode())
// after
bt = "L2_MBP"  # canonical BookType spelling; prefer book_type_to_cstr(BookType.L2_MBP)
book_type_from_cstr(bt.encode())
Defensive patterns

Strategy: validation

Validate before calling

VALID_BOOK_TYPES = {"L1_MBP", "L2_MBP", "L3_MBO"}  # verify against BookType definition
assert bt_str in VALID_BOOK_TYPES, f"bad BookType: {bt_str!r}"
book_type_from_cstr(bt_str.encode())

Type guard

def is_valid_book_type(s: str) -> bool:
    return s in VALID_BOOK_TYPES  # canonical strings from BookType::as_ref

Prevention

When it happens

Trigger: Calling `book_type_from_cstr(ptr)` with strings like 'l2'/'depth2' in the wrong form, an empty string, or a value from another vendor's book-type naming scheme.

Common situations: Configuring order book depth in a data-engine config; adapters translating venue depth levels into `BookType`; case/typo mistakes; enum spelling changes across NautilusTrader versions.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/41f937a62a8fade3. Report an issue: GitHub.