nautechsystems/nautilus_trader · error · serde_json::Error
JSON does not represent CustomData
Error message
JSON does not represent CustomData
What it means
parse_custom_data_from_json_bytes deserializes a JSON payload into the model's Data enum and requires the variant to be Data::Custom. If the JSON parses as valid Data but represents a different type (quote, trade, bar, etc.), an InvalidData io-backed serde_json error is raised with "JSON does not represent CustomData". It means the caller asked for CustomData but supplied JSON of another Data kind.
Source
Thrown at crates/model/src/data/custom.rs:427
impl PartialEq for CustomData {
fn eq(&self, other: &Self) -> bool {
self.data.eq_arc(other.data.as_ref()) && self.data_type == other.data_type
}
}
impl HasTsInit for CustomData {
fn ts_init(&self) -> UnixNanos {
self.data.ts_init()
}
}
pub(crate) fn parse_custom_data_from_json_bytes(
bytes: &[u8],
) -> Result<CustomData, serde_json::Error> {
let data: Data = serde_json::from_slice(bytes)?;
match data {
Data::Custom(custom) => Ok(custom),
_ => Err(serde_json::Error::io(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"JSON does not represent CustomData",
))),
}
}
impl CustomData {
/// Deserializes `CustomData` from JSON bytes (full `CustomData` format with type and `data_type`).
///
/// # Errors
///
/// Returns an error if the bytes are not valid JSON or do not represent `CustomData`.
pub fn from_json_bytes(bytes: &[u8]) -> Result<Self, serde_json::Error> {
parse_custom_data_from_json_bytes(bytes)
}
}
/// Canonical JSON envelope for `CustomData`. All serialized `CustomData` uses this shape soView on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the JSON's "type" field and use the matching from_json_bytes parser for that Data type.
- Re-export/persist the data ensuring it was serialized as CustomData (type tag "custom").
- If parsing heterogeneous Data, parse into Data first and route on the variant instead of calling the custom-only parser.
- Validate the payload's type tag before calling parse_custom_data_from_json_bytes.
Example fix
// before
let custom = CustomData::from_json_bytes(bytes)?;
// after
let data: Data = serde_json::from_slice(bytes)?;
let custom = match data {
Data::Custom(c) => c,
other => anyhow::bail!("expected CustomData, got {:?}", other),
}; Defensive patterns
Strategy: validation
Validate before calling
fn is_custom_data_json(bytes: &[u8]) -> bool {
serde_json::from_slice::<serde_json::Value>(bytes)
.ok()
.and_then(|v| v.get("type").and_then(|t| t.as_str()).map(|s| s == "CustomData".to_owned() || s == "custom"))
.unwrap_or(false)
} Type guard
fn as_custom_data(data: &Data) -> Option<&CustomData> {
match data { Data::Custom(c) => Some(c), _ => None }
} Try / catch
match CustomData::from_json_bytes(bytes) {
Ok(custom) => handle(custom),
Err(e) if e.to_string().contains("does not represent CustomData") => {
let data: Data = serde_json::from_slice(bytes)?;
route_by_variant(data); // dispatch to the right parser
}
Err(e) => return Err(e.into()),
} Prevention
- Check the JSON "type" tag before choosing a from_json_bytes parser
- Persist Data payloads with their type tags intact
- Route heterogeneous data through a variant dispatch, not a custom-only parser
- Never assume user-supplied JSON is CustomData
When it happens
Trigger: Calling CustomData.from_json_bytes (or its Python binding py_from_json_bytes_py) with bytes that decode to a Data JSON object for a non-custom variant, e.g. a serialized QuoteTick, TradeTick, Bar, or Delta.
Common situations: Mixing up files in a data pipeline (feeding bar JSON where custom data is expected); writing generic Data JSON to disk and later assuming it is custom; passing user-supplied payloads to the custom-data parser without checking the "type" field.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Python object has no to_json() method or __dict__ attribute
- from_json not implemented for {}
- Instances must have encode_record_batch_py method
- Expected {}, was different type
- CustomData envelope type '{envelope_type_name}' does not mat
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/cf4c03d694af5894.
Report an issue: GitHub.