nautechsystems/nautilus_trader · critical

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

Error message

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

What it means

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.

Source

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

pub extern "C" fn account_type_to_cstr(value: AccountType) -> *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 `AccountType` variant.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn account_type_from_cstr(ptr: *const c_char) -> AccountType {
    abort_on_panic(|| {
        let value = unsafe { cstr_as_str(ptr) };
        AccountType::from_str(value)
            .unwrap_or_else(|_| panic!("invalid `AccountType` enum string value, was '{value}'"))
    })
}

#[unsafe(no_mangle)]
pub extern "C" fn aggregation_source_to_cstr(value: AggregationSource) -> *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 `AggregationSource` variant.
#[unsafe(no_mangle)]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the string exactly matches a valid AccountType variant (case and spelling)
  2. Validate the value in the host language against the enum's known values before calling the FFI function
  3. Rebuild bindings after upgrading so enum string tables stay in sync

Example fix

// before
let account_type = account_type_from_cstr(c"margin"); // wrong case -> abort
// after
let value = "MARGIN"; // must match AccountType::from_str accepted values
let account_type = account_type_from_cstr(CString::new(value).unwrap().as_ptr());
Defensive patterns

Strategy: validation

Validate before calling

// Host-side (Python/C) validation before the FFI call
VALID_ACCOUNT_TYPES = {"CASH", "MARGIN", "CASH_AND_MARGIN"}
if value not in VALID_ACCOUNT_TYPES:
    raise ValueError(f"invalid AccountType: {value!r}")

Try / catch

// FFI panics abort, so validate first; there is nothing to catch
assert!(VALID.contains(&value.as_str()), "invalid AccountType: {value}");
let account_type = unsafe { account_type_from_cstr(ptr) };

Prevention

When it happens

Trigger: 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).

Common situations: 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.

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/ea851662b1cfe559. Report an issue: GitHub.