{"record":{"id":"3dcac5a616ecd31a","repo":"nautechsystems/nautilus_trader","slug":"invalid-instrumentclass-enum-string-value-was","errorCode":null,"errorMessage":"invalid `InstrumentClass` enum string value, was '{value}'","messagePattern":"invalid `InstrumentClass` enum string value, was '(.+?)'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/model/src/ffi/enums.rs","lineNumber":388,"sourceCode":"pub extern \"C\" fn instrument_class_to_cstr(value: InstrumentClass) -> *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 `InstrumentClass` variant.\n#[unsafe(no_mangle)]\npub unsafe extern \"C\" fn instrument_class_from_cstr(ptr: *const c_char) -> InstrumentClass {\n    abort_on_panic(|| {\n        let value = unsafe { cstr_as_str(ptr) };\n        InstrumentClass::from_str(value).unwrap_or_else(|_| {\n            panic!(\"invalid `InstrumentClass` enum string value, was '{value}'\")\n        })\n    })\n}\n\n#[unsafe(no_mangle)]\npub extern \"C\" fn bar_aggregation_to_cstr(value: BarAggregation) -> *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 `BarAggregation` variant.","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/ffi/enums.rs#L370-L406","documentation":"`instrument_class_from_cstr` converts a C string into the Rust `InstrumentClass` enum and panics when the string matches no variant. The library cannot represent an unknown instrument class, so it panics — and because this is an FFI boundary, `abort_on_panic` turns the panic into a process abort. Accepted strings are exactly the `InstrumentClass` serializations produced by `instrument_class_to_cstr`.","triggerScenarios":"Calling `instrument_class_from_cstr(ptr)` with a non-canonical instrument-class string (e.g. 'perpetual' instead of the canonical variant spelling), an empty string, or a value whose spelling differs from the current enum definition.","commonSituations":"Loading instruments from external catalogs with their own class vocabulary; typos in config; passing an older library's serialization after an upgrade; confusing `AssetClass` with `InstrumentClass` — they are different enums with different vocabularies.","solutions":["Dump the exact string at the call site and diff it against the canonical `InstrumentClass` variant strings.","Use the library's `InstrumentClass` enum plus `instrument_class_to_cstr` to produce valid strings instead of hand-written ones.","Confirm you are using the right enum — `InstrumentClass` (instrument kinds like SPOT/FUTURE) differs from `AssetClass`.","Whitelist/map external catalog class names to `InstrumentClass` before calling the FFI.","Normalize case/whitespace; the FromStr match is exact, and failure aborts the process."],"exampleFix":"// before\ncls = \"PERPETUAL\"\ninstrument_class_from_cstr(cls.encode())\n// after\ncls = \"PERP\"  # canonical InstrumentClass variant string (verify in enum definition)\ninstrument_class_from_cstr(cls.encode())","handlingStrategy":"validation","validationCode":"VALID_INSTRUMENT_CLASSES = {\"SPOT\", \"FUTURE\", \"OPTION\"}  # from InstrumentClass definition\nassert class_str in VALID_INSTRUMENT_CLASSES, f\"bad InstrumentClass: {class_str!r}\"\ninstrument_class_from_cstr(class_str.encode())","typeGuard":"def is_valid_instrument_class(s: str) -> bool:\n    return s in VALID_INSTRUMENT_CLASSES  # canonical strings from InstrumentClass::as_ref","tryCatchPattern":null,"preventionTips":["Do not confuse AssetClass and InstrumentClass vocabularies; they are different enums.","Derive strings via instrument_class_to_cstr rather than literals.","Normalize case/whitespace at the boundary.","Validate external catalog terms against the canonical set before the FFI call.","Re-verify spellings after library 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"}