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 so

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the JSON's "type" field and use the matching from_json_bytes parser for that Data type.
  2. Re-export/persist the data ensuring it was serialized as CustomData (type tag "custom").
  3. If parsing heterogeneous Data, parse into Data first and route on the variant instead of calling the custom-only parser.
  4. 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

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


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