{"record":{"id":"ea851662b1cfe559","repo":"nautechsystems/nautilus_trader","slug":"invalid-accounttype-enum-string-value-was-val","errorCode":null,"errorMessage":"invalid `AccountType` enum string value, was '{value}'","messagePattern":"invalid `AccountType` enum string value, was '(.+?)'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/model/src/ffi/enums.rs","lineNumber":295,"sourceCode":"pub extern \"C\" fn account_type_to_cstr(value: AccountType) -> *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 `AccountType` variant.\n#[unsafe(no_mangle)]\npub unsafe extern \"C\" fn account_type_from_cstr(ptr: *const c_char) -> AccountType {\n    abort_on_panic(|| {\n        let value = unsafe { cstr_as_str(ptr) };\n        AccountType::from_str(value)\n            .unwrap_or_else(|_| panic!(\"invalid `AccountType` enum string value, was '{value}'\"))\n    })\n}\n\n#[unsafe(no_mangle)]\npub extern \"C\" fn aggregation_source_to_cstr(value: AggregationSource) -> *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 `AggregationSource` variant.\n#[unsafe(no_mangle)]","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/ffi/enums.rs#L277-L313","documentation":"FFI helper account_type_from_cstr converts a C string to a Rust AccountType enum and aborts the process (via abort_on_panic) if the string does not parse to a valid variant. Because it runs across the FFI boundary, panics are converted to aborts — unrecoverable for the host process.","triggerScenarios":"Passing a C string to account_type_from_cstr whose value is not one of the AccountType variants (e.g. 'MARGIN' vs expected 'CASH'/'MARGIN'/'CASH_AND_MARGIN', or a truncated/garbage string).","commonSituations":"Python/C bindings passing user config strings without validating against the enum; version drift where an enum value was renamed; localized or lowercase account-type labels in config.","solutions":["Ensure the string exactly matches a valid AccountType variant (case and spelling)","Validate the value in the host language against the enum's known values before calling the FFI function","Rebuild bindings after upgrading so enum string tables stay in sync"],"exampleFix":"// before\nlet account_type = account_type_from_cstr(c\"margin\"); // wrong case -> abort\n// after\nlet value = \"MARGIN\"; // must match AccountType::from_str accepted values\nlet account_type = account_type_from_cstr(CString::new(value).unwrap().as_ptr());","handlingStrategy":"validation","validationCode":"// Host-side (Python/C) validation before the FFI call\nVALID_ACCOUNT_TYPES = {\"CASH\", \"MARGIN\", \"CASH_AND_MARGIN\"}\nif value not in VALID_ACCOUNT_TYPES:\n    raise ValueError(f\"invalid AccountType: {value!r}\")","typeGuard":null,"tryCatchPattern":"// FFI panics abort, so validate first; there is nothing to catch\nassert!(VALID.contains(&value.as_str()), \"invalid AccountType: {value}\");\nlet account_type = unsafe { account_type_from_cstr(ptr) };","preventionTips":["Never pass user config strings directly across the FFI boundary; validate against the known variant list first","Keep host-language enum mirrors in sync with the Rust enum on upgrades","Treat any FFI panic as process-fatal and design startup validation to catch bad values earlier"],"tags":["rust","ffi","panic-abort","enum-parsing"],"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"}