{"record":{"id":"9a0f6889f09b8b2b","repo":"nautechsystems/nautilus_trader","slug":"invalid-bookaction-enum-string-value-was-valu","errorCode":null,"errorMessage":"invalid `BookAction` enum string value, was '{value}'","messagePattern":"invalid `BookAction` enum string value, was '(.+?)'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/model/src/ffi/enums.rs","lineNumber":435,"sourceCode":"pub extern \"C\" fn book_action_to_cstr(value: BookAction) -> *const c_char {\n    str_to_cstr(value.as_ref())\n}\n\n/// Returns an enum from a C string.\n///\n/// # Safety\n///\n/// Assumes `ptr` is a valid C string pointer.\n///\n/// # Panics\n///\n/// Panics if the C string does not correspond to a valid `BookAction` variant.\n#[unsafe(no_mangle)]\npub unsafe extern \"C\" fn book_action_from_cstr(ptr: *const c_char) -> BookAction {\n    abort_on_panic(|| {\n        let value = unsafe { cstr_as_str(ptr) };\n        BookAction::from_str(value)\n            .unwrap_or_else(|_| panic!(\"invalid `BookAction` enum string value, was '{value}'\"))\n    })\n}\n\n#[unsafe(no_mangle)]\npub extern \"C\" fn book_type_to_cstr(value: BookType) -> *const c_char {\n    str_to_cstr(value.as_ref())\n}\n\n/// Returns an enum from a C string.\n///\n/// # Safety\n///\n/// Assumes `ptr` is a valid C string pointer.\n///\n/// # Panics\n///\n/// Panics if the C string does not correspond to a valid `BookType` variant.\n#[unsafe(no_mangle)]","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/ffi/enums.rs#L417-L453","documentation":"`book_action_from_cstr` converts a C string to the Rust `BookAction` enum and panics when the string is not a recognized variant. Because the function crosses the C FFI boundary, the panic is contained by `abort_on_panic` and aborts the host process. Only exact canonical serializations from `book_action_to_cstr` are valid input.","triggerScenarios":"Calling `book_action_from_cstr(ptr)` with a non-canonical action string (e.g. 'insert'/'remove' instead of the canonical ADD/DELETE spellings), an empty string, or a string from a different order-book action vocabulary.","commonSituations":"Mapping a market data feed's book event actions to Nautilus's `BookAction`; typos in adapter code; case mismatches; version drift after enum renames.","solutions":["Log the exact string and compare with the canonical `BookAction` variant spellings in the model enums.","Map feed-specific action names explicitly (feed action -> BookAction string) at the adapter boundary.","Normalize case/whitespace before calling; the match is exact.","Generate strings via `book_action_to_cstr` from enum values instead of literals.","Validate the string against the known set before the FFI call, since failure aborts the process."],"exampleFix":"// before\naction = \"remove\"\nbook_action_from_cstr(action.encode())\n// after\naction = \"DELETE\"  # canonical BookAction variant string\nbook_action_from_cstr(action.encode())","handlingStrategy":"validation","validationCode":"VALID_BOOK_ACTIONS = {\"ADD\", \"UPDATE\", \"DELETE\", \"CLEAR\"}  # verify against BookAction definition\nassert action_str in VALID_BOOK_ACTIONS, f\"bad BookAction: {action_str!r}\"\nbook_action_from_cstr(action_str.encode())","typeGuard":"def is_valid_book_action(s: str) -> bool:\n    return s in VALID_BOOK_ACTIONS  # canonical strings from BookAction::as_ref","tryCatchPattern":null,"preventionTips":["Map feed-specific book-event actions to BookAction strings explicitly at the adapter.","Normalize case/whitespace before the FFI call.","Validate against the accepted set to avoid a process abort.","Derive strings via book_action_to_cstr instead of literals.","Diff hard-coded strings against the enum after upgrades."],"tags":["ffi","rust","panic","enum-parsing","process-abort"],"backgroundTag":"invalid-enum-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}