nautechsystems/nautilus_trader · error

JSON string contains interior null bytes

Error message

JSON string contains interior null bytes

What it means

Panic in `string_vec_to_bytes`: after serializing to JSON, `CString::new(json_string).expect("JSON string contains interior null bytes")` aborts if the JSON text contains an interior NUL byte. Since CString cannot represent interior nulls, the library treats such output as a contract violation. For normal string contents serde_json escapes NULs as \u0000, so this is also effectively unreachable for plain strings.

Solutions

  1. Inspect the input strings for raw NUL bytes and strip them at the source if feeding non-standard data
  2. Do not post-process/replace within the serialized JSON before conversion
  3. Use the standard serde_json version; rebuild if a patched dependency is present
  4. If reproducible with plain strings, report it — the expected behavior is escaped \u0000, no panic

Example fix

// before
let s = String::from_utf8(vec![b'a', 0, b'b']).unwrap(); // raw interior NUL handled ad-hoc
// after
let cleaned: String = s.chars().filter(|&c| c != '\0').collect();
let ptr = string_vec_to_bytes(&[cleaned]);
Defensive patterns

Strategy: validation

Validate before calling

assert!(!json_string.contains('\0'), "JSON payload must not contain raw NUL bytes");

Try / catch

let result = std::panic::catch_unwind(|| string_vec_to_bytes(strings));
if result.is_err() { eprintln!("interior NUL in serialized JSON"); }

Prevention

When it happens

Trigger: Calling `string_vec_to_bytes` when the serialized JSON unexpectedly contains a raw interior null byte — realistically only via non-standard serialization output or corrupted string data, not ordinary `Vec<String>` content.

Common situations: Very rare: custom string types or patched serializers emitting raw NULs; post-processing the JSON string before passing it in; memory corruption. Ordinary usage (strings containing '\0') is safe because serde_json escapes them.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/972d16b35a755d48. Report an issue: GitHub.

Appendix: source

Thrown at crates/core/src/ffi/parsing.rs:85

    arr.iter()
        .map(|value| {
            value
                .as_str()
                .expect("C string JSON array must contain only strings")
                .to_owned()
        })
        .collect()
}

/// Convert a slice of `String` into a C string pointer (JSON encoded).
///
/// # Panics
///
/// Panics if JSON serialization fails or if the generated string contains interior null bytes.
#[must_use]
pub fn string_vec_to_bytes(strings: &[String]) -> *const c_char {
    let json_string = serde_json::to_string(strings).expect("Failed to serialize strings to JSON");
    let c_string = CString::new(json_string).expect("JSON string contains interior null bytes");

    c_string.into_raw()
}

/// Convert a C bytes pointer into an owned `Option<HashMap<String, Value>>`.
///
/// # Safety
///
/// Assumes `ptr` is a valid C string pointer.
///
/// # Panics
///
/// Panics if `ptr` is not null but contains invalid UTF-8 or JSON.
#[must_use]
pub unsafe fn optional_bytes_to_json(ptr: *const c_char) -> Option<HashMap<String, Value>> {
    // SAFETY: A non-null pointer is valid under the caller's contract
    unsafe { optional_json_from_cstr(ptr) }
}

View on GitHub (pinned to 18893faf8b)