nautechsystems/nautilus_trader · error · anyhow::Error
CustomData value must be valid JSON: {e}
Error message
CustomData value must be valid JSON: {e} What it means
Raised in `add_custom_data` when the freshly serialized CustomData bytes fail to parse back via `serde_json::from_slice`. This is a defensive round-trip check before extracting the `data_type` field; failure indicates the serialized bytes are not valid JSON (rare, usually a bug or non-UTF8/binary payload) .
Source
Thrown at crates/infrastructure/src/sql/queries.rs:1622
.bind(name)
.fetch_all(pool)
.await
.map(|rows| rows.into_iter().map(|row| row.0).collect())
.map_err(|e| anyhow::anyhow!("Failed to load signals: {e}"))
}
/// Inserts a `CustomData` entry via the provided `pool`.
///
/// Serializes the model `CustomData` to full JSON and stores it in the JSONB `value` column.
///
/// # Errors
///
/// Returns an error if the SQL INSERT operation fails.
pub async fn add_custom_data(pool: &PgPool, data: &CustomData) -> anyhow::Result<()> {
let json_bytes = serde_json::to_vec(data)
.map_err(|e| anyhow::anyhow!("CustomData must be valid JSON: {e}"))?;
let value_json: serde_json::Value = serde_json::from_slice(&json_bytes)
.map_err(|e| anyhow::anyhow!("CustomData value must be valid JSON: {e}"))?;
let data_type_obj = value_json
.get("data_type")
.and_then(|v| v.as_object())
.ok_or_else(|| anyhow::anyhow!("CustomData JSON missing data_type"))?;
let data_type_name = data_type_obj
.get("type_name")
.and_then(|v| v.as_str())
.unwrap_or("");
let metadata_json = data_type_obj
.get("metadata")
.cloned()
.unwrap_or_else(|| serde_json::Value::Object(serde_json::Map::new()));
let identifier = data_type_obj
.get("identifier")
.and_then(|v| v.as_str())
.unwrap_or("");
sqlx::query(
r#"View on GitHub (pinned to 18893faf8b)
Solutions
- Confirm the payload serializes and deserializes cleanly with serde_json::to_vec/from_slice in a unit test.
- Inspect the serde_json error in `{e}` for the offset of the invalid byte.
- Avoid custom Serialize impls; derive Serialize/Deserialize on the payload type.
- Update to matching versions of the data model crate so serialization output is well-formed.
Defensive patterns
Strategy: validation
Validate before calling
let bytes = serde_json::to_vec(&data)?;
serde_json::from_slice::<serde_json::Value>(&bytes)
.map_err(|e| anyhow::anyhow!("payload does not round-trip: {e}"))?; Type guard
fn round_trips<T: serde::Serialize>(v: &T) -> bool {
serde_json::to_vec(v)
.ok()
.map(|b| serde_json::from_slice::<serde_json::Value>(&b).is_ok())
.unwrap_or(false)
} Prevention
- Unit-test Serialize/Deserialize round-trips for custom data types
- Avoid custom Serialize impls emitting non-standard JSON
- Keep the data model crate versions consistent
When it happens
Trigger: Calling `add_custom_data` when serialization produced bytes that serde_json cannot parse back — e.g., a custom Serialize impl emitting invalid JSON, or corrupted intermediate representation.
Common situations: Hand-written Serialize implementations producing malformed output; exotic custom data payloads; library version mismatch where CustomData's serialized shape changed.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- serde_json deserialization error: {e}
- Failed to serialize exec algorithm params: {e}
- Failed to serialize order event info: {e}
- Failed to decode position replay state: {e}
- Failed to serialize fill info: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0224e0406c5e64f4.
Report an issue: GitHub.