nautechsystems/nautilus_trader · error · anyhow::Error
CustomData must be valid JSON: {e}
Error message
CustomData must be valid JSON: {e} What it means
Raised in `add_custom_data` when `serde_json::to_vec(data)` fails to serialize the `CustomData` struct. Since CustomData is Rust data, this usually means a serialization error inside its payload (e.g., a map with non-string keys, or an internal Serialize impl returning an error). The library requires CustomData to round-trip through JSON because it is stored in a JSONB column.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:1620
r#"SELECT * FROM "signal" WHERE name = $1 ORDER BY ts_init ASC"#,
)
.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("");View on GitHub (pinned to 18893faf8b)
Solutions
- Check the serde error in `{e}` for the exact field that failed to serialize.
- Replace NaN/Infinity floats with valid JSON-representable values or strings.
- Ensure map keys in the payload are strings (or convert before constructing CustomData).
- Validate the payload round-trips with serde_json::to_vec before calling the API.
Example fix
// before
let data = CustomData::new(my_value, ...); // my_value contains HashMap<u64, String>
add_custom_data(&pool, &data).await?;
// after
let normalized = my_value.iter().map(|(k, v)| (k.to_string(), v.clone())).collect::<HashMap<String, _>>();
serde_json::to_vec(&normalized).expect("valid JSON");
add_custom_data(&pool, &CustomData::new(normalized, ...)).await?; Defensive patterns
Strategy: validation
Validate before calling
// verify the payload serializes before calling the API
let bytes = serde_json::to_vec(&data)
.map_err(|e| anyhow::anyhow!("CustomData not JSON-serializable: {e}"))?;
anyhow::ensure!(!bytes.is_empty(), "empty CustomData payload"); Type guard
fn is_json_serializable<T: serde::Serialize>(v: &T) -> bool {
serde_json::to_vec(v).is_ok()
} Prevention
- Avoid NaN/Infinity floats in custom data payloads
- Use string map keys in payloads and metadata
- Derive Serialize instead of hand-writing it
- Round-trip test payloads in unit tests
When it happens
Trigger: Calling `add_custom_data(pool, data)` with a CustomData whose inner value or metadata cannot be represented as JSON (non-string map keys, unsupported numeric types like NaN/Infinity in a JSON-restricted serializer, or a failing custom Serialize implementation).
Common situations: Custom data payloads containing f64 NaN/Infinity; user-defined data types with hand-written Serialize impls that error; non-string-key maps (e.g., HashMap<u32, _>) in metadata.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- Failed to serialize exec algorithm params: {e}
- Failed to serialize order event info: {e}
- Failed to serialize fill info: {e}
- Failed to serialize account event: {e}
- Failed to serialize JSON: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4a609f3d79d8f34f.
Report an issue: GitHub.