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

  1. Check the serde error in `{e}` for the exact field that failed to serialize.
  2. Replace NaN/Infinity floats with valid JSON-representable values or strings.
  3. Ensure map keys in the payload are strings (or convert before constructing CustomData).
  4. 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

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


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