{"record":{"id":"1cd832fbd5c19819","repo":"nautechsystems/nautilus_trader","slug":"c-string-json-array-must-contain-only-strings","errorCode":null,"errorMessage":"C string JSON array must contain only strings","messagePattern":"C string JSON array must contain only strings","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/core/src/ffi/parsing.rs","lineNumber":71,"sourceCode":"    assert!(!ptr.is_null(), \"`ptr` was NULL\");\n\n    // SAFETY: Caller guarantees ptr is valid per function contract\n    let c_str = unsafe { CStr::from_ptr(ptr) };\n    let bytes = c_str.to_bytes();\n\n    let json_string = std::str::from_utf8(bytes).expect(\"C string contains invalid UTF-8\");\n    let value: serde_json::Value =\n        serde_json::from_str(json_string).expect(\"C string contains invalid JSON\");\n\n    let arr = value\n        .as_array()\n        .expect(\"C string JSON must be an array of strings\");\n\n    arr.iter()\n        .map(|value| {\n            value\n                .as_str()\n                .expect(\"C string JSON array must contain only strings\")\n                .to_owned()\n        })\n        .collect()\n}\n\n/// Convert a slice of `String` into a C string pointer (JSON encoded).\n///\n/// # Panics\n///\n/// Panics if JSON serialization fails or if the generated string contains interior null bytes.\n#[must_use]\npub fn string_vec_to_bytes(strings: &[String]) -> *const c_char {\n    let json_string = serde_json::to_string(strings).expect(\"Failed to serialize strings to JSON\");\n    let c_string = CString::new(json_string).expect(\"JSON string contains interior null bytes\");\n\n    c_string.into_raw()\n}\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/core/src/ffi/parsing.rs#L53-L89","documentation":"Panic in `bytes_to_string_vec` when the JSON array contains non-string elements. Each element goes through `value.as_str().expect(\"C string JSON array must contain only strings\")`, so numbers, nulls, booleans, or nested arrays inside the array cause a panic. The FFI wire format is strictly `Vec<String>` encoded as JSON.","triggerScenarios":"Passing a C string holding e.g. `[\"a\", 1, null]` into `bytes_to_string_vec`, or through the synthetic-instrument FFI entry points that consume component lists.","commonSituations":"Serializing a mixed-type list (e.g. Python `list` containing ints/None) on the calling-language side; loose JSON construction in scripts; dynamic data where a component is accidentally `None` and serialized as null.","solutions":["Coerce all elements to strings before serializing (e.g. `[str(x) for x in items]` in Python)","Filter out or stringify None/null entries prior to `string_vec_to_bytes`","Validate the JSON with a schema (`array of string`) at the boundary in debug builds","Ensure the producer language's list is homogeneous before crossing FFI"],"exampleFix":"# before (Python side)\ncomponents = [\"ema\", 10, None]\n# after\ncomponents = [str(x) for x in components if x is not None]","handlingStrategy":"validation","validationCode":"if not all(isinstance(x, str) for x in components):\n    components = [str(x) for x in components if x is not None]","typeGuard":"fn all_strings(items: &[serde_json::Value]) -> bool { items.iter().all(|v| v.is_string()) }","tryCatchPattern":"let vals: Vec<serde_json::Value> = serde_json::from_str(text)?;\nif !vals.iter().all(|v| v.is_string()) { return Err(ParsingError::NonStringElement); }","preventionTips":["Coerce heterogeneous lists to strings before serialization","Filter null/None entries at the source","Use typed lists (list[str]) in the calling language","Validate with a JSON schema (array of strings) in tests"],"tags":["rust","ffi","json","panic","type-mismatch"],"backgroundTag":"type-mismatch","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"}