{"record":{"id":"ea9c821700d9350a","repo":"nautechsystems/nautilus_trader","slug":"error-converting-enum","errorCode":null,"errorMessage":"Error converting enum","messagePattern":"Error converting enum","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/ffi/data/bar.rs","lineNumber":45,"sourceCode":"\nuse crate::{\n    data::bar::{Bar, BarSpecification, BarType},\n    enums::{AggregationSource, BarAggregation, PriceType},\n    identifiers::InstrumentId,\n    types::{Price, Quantity},\n};\n\n/// # Panics\n///\n/// Panics if `aggregation` or `price_type` do not correspond to valid enum variants.\n#[unsafe(no_mangle)]\npub extern \"C\" fn bar_specification_new(\n    step: usize,\n    aggregation: u8,\n    price_type: u8,\n) -> BarSpecification {\n    let aggregation =\n        BarAggregation::from_repr(aggregation as usize).expect(\"Error converting enum\");\n    let price_type = PriceType::from_repr(price_type as usize).expect(\"Error converting enum\");\n    BarSpecification::new(step, aggregation, price_type)\n}\n\n/// Returns a [`BarSpecification`] as a C string pointer.\n#[unsafe(no_mangle)]\npub extern \"C\" fn bar_specification_to_cstr(bar_spec: &BarSpecification) -> *const c_char {\n    str_to_cstr(&bar_spec.to_string())\n}\n\n#[unsafe(no_mangle)]\npub extern \"C\" fn bar_specification_hash(bar_spec: &BarSpecification) -> u64 {\n    let mut h = DefaultHasher::new();\n    bar_spec.hash(&mut h);\n    h.finish()\n}\n\n#[unsafe(no_mangle)]","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/ffi/data/bar.rs#L27-L63","documentation":"bar_specification_new is a C FFI constructor that receives the bar aggregation as a raw u8 discriminator and converts it with BarAggregation::from_repr(...).expect(\"Error converting enum\"). If the u8 does not map to a valid BarAggregation variant, the expect panics. The library throws it because the FFI boundary cannot return a Result and treats an unknown discriminant as a caller contract violation.","triggerScenarios":"Calling the exported bar_specification_new from Python/FFI with an aggregation byte outside the valid BarAggregation repr range (e.g. 0, 255, or an int from a stale/foreign enum table).","commonSituations":"Version mismatch between the Cython-generated bindings and the compiled Rust extension (enum discriminants shifted), hand-rolled ctypes/cffi calls passing the wrong constant, or a script building specs from unvalidated config values.","solutions":["Pass aggregation values only from the bindings' own BarAggregation enum (e.g. nautilus_model.core.data enums), not hand-picked integers.","Rebuild/reinstall the package so the Cython bindings and Rust extension are from the same version.","Validate the configured aggregation string (e.g. \"MINUTE\", \"TICK\") against the enum before lowering to a byte.","If writing raw FFI, add a caller-side check that the byte is in the documented repr range before invoking."],"exampleFix":"// before (Python FFI call)\nbar_specification_new(1, 7, 1)  # 7 is not a valid BarAggregation\n// after\nbar_specification_new(1, int(BarAggregation.MINUTE), int(PriceType.LAST))","handlingStrategy":"validation","validationCode":"# Python caller\nVALID_AGGREGATIONS = set(range(1, len(BarAggregation) + 1))\nassert aggregation in VALID_AGGREGATIONS, f\"bad aggregation repr {aggregation}\"","typeGuard":"def is_valid_aggregation(v: int) -> bool:\n    try:\n        BarAggregation(v)\n        return True\n    except ValueError:\n        return False","tryCatchPattern":null,"preventionTips":["Always pass enum members, never raw integers, across the FFI boundary.","Keep Rust crate and Cython bindings versions in lockstep.","Validate config strings against the enum before lowering to a byte."],"tags":["ffi","enum","panic","invalid-argument","rust"],"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-14T00:17:10.932Z"}