nautechsystems/nautilus_trader · error
CustomData serialization failed: {e}
Error message
CustomData serialization failed: {e} What it means
add_custom_data serializes a CustomData record to JSON bytes before writing it to the Redis-backed cache. If serde_json cannot serialize the record, the failure is wrapped in this anyhow error. It surfaces when the payload contains types with no JSON representation (e.g. non-string map keys) or internal serialization bugs.
Source
Thrown at crates/infrastructure/src/redis/cache.rs:508
/// # Errors
///
/// Returns an error if the command cannot be sent to the background task channel.
pub fn insert(&self, key: String, payload: Option<Vec<Bytes>>) -> anyhow::Result<()> {
let op = DatabaseCommand::new(DatabaseOperation::Insert, key, payload);
match self.tx.send(op) {
Ok(()) => Ok(()),
Err(e) => anyhow::bail!("{FAILED_TX_CHANNEL}: {e}"),
}
}
/// Stores custom data in Redis (key format: `custom:<ts_init_020>:<uuid>`, value: full JSON).
///
/// # Errors
///
/// Returns an error if serialization fails or the insert command cannot be sent.
pub fn add_custom_data(&self, data: &CustomData) -> anyhow::Result<()> {
let json_bytes = serde_json::to_vec(data)
.map_err(|e| anyhow::anyhow!("CustomData serialization failed: {e}"))?;
let ts_init = data.ts_init().as_u64();
let key = format!(
"{CUSTOM}{REDIS_DELIMITER}{:020}{REDIS_DELIMITER}{}",
ts_init,
UUID4::new()
);
self.insert(key, Some(vec![Bytes::from(json_bytes)]))
}
/// Sends an update command for `key` with optional `payload` to Redis via the background task.
///
/// # Errors
///
/// Returns an error if the command cannot be sent to the background task channel.
pub fn update(&mut self, key: String, payload: Option<Vec<Bytes>>) -> anyhow::Result<()> {
let op = DatabaseCommand::new(DatabaseOperation::Update, key, payload);
match self.tx.send(op) {
Ok(()) => Ok(()),View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the serde message in the error to find the field that cannot be serialized and change its type (e.g. use string keys in maps).
- Ensure the CustomData type derives Serialize and all nested types have JSON-compatible representations.
- Upgrade nautilus_trader if a recent version had a serialization bug affecting your data type.
- If the type cannot be JSON-serialized, convert it to a supported representation before passing to add_custom_data.
Example fix
// before let data = MyData::new(my_map_with_int_keys); cache.add_custom_data(&data)?; // fails: key must be a string // after let data = MyData::new(my_map_with_string_keys); cache.add_custom_data(&data)?;
Defensive patterns
Strategy: validation
Validate before calling
let json = serde_json::to_vec(&data).map_err(|e| format!("custom data not JSON-serializable: {e}"))?; Type guard
fn is_json_serializable<T: serde::Serialize>(v: &T) -> bool { serde_json::to_vec(v).is_ok() } Prevention
- Use only JSON-compatible field types (string map keys, no non-string keys) in custom Data types.
- Unit-test serialization of every custom data type before adding it to the cache.
- Derive Serialize/Deserialize and keep nested types JSON-friendly.
When it happens
Trigger: Calling add_custom_data (directly or via the Python wrapper py_add_custom_data) with a CustomData whose serde serialization fails — typically data containing maps with non-string keys or unsupported field types.
Common situations: Users feed custom market data or metadata into the cache containing structures serde_json cannot encode; usually introduced by a custom Data subtype with exotic field types added in a recent change.
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
- UnixNanos is within Jiff's timestamp range
- Close command should not be drained
- Flush command should not be drained
- Redis config error: username supplied without password. Eith
- Unknown execution event marker {event}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/fcfce0814d09c35d.
Report an issue: GitHub.