nautechsystems/nautilus_trader · error
Failed to serialize config value: {e}
Error message
Failed to serialize config value: {e} What it means
Raised by `config_value_to_py` when a single config value cannot be serialized to JSON with `serde_json::to_string` as part of converting the Rust config map into a Python dict. Values like StrategyId are handled specially; anything else goes through serde_json, which fails for non-serializable types (e.g. maps with non-string keys, arbitrary Rust types without Serialize).
Source
Thrown at crates/backtest/src/python/node.rs:598
) -> anyhow::Result<Bound<'py, PyAny>> {
if key == "actor_id"
&& let Some(actor_id) = value.as_str()
{
return Ok(ActorId::new_checked(actor_id)?
.into_pyobject(py)?
.into_any());
}
if key == "strategy_id"
&& let Some(strategy_id) = value.as_str()
{
return Ok(StrategyId::new_checked(strategy_id)?
.into_pyobject(py)?
.into_any());
}
let json_str = serde_json::to_string(value)
.map_err(|e| anyhow::anyhow!("Failed to serialize config value: {e}"))?;
Ok(PyModule::import(py, "json")?
.call_method("loads", (json_str,), None)?
.into_any())
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Convert non-string map keys to Strings before putting them in the config
- Sanitize floats: replace NaN/Infinity with valid values or omit the entry
- Use only JSON-compatible types (string, bool, i64/u64, f64 finite, Vec, String-keyed map) for config values
- If it is a custom type, implement Serialize/Deserialize for it in a JSON-compatible form
Example fix
// before
let config: HashMap<String, ConfigValue> = ...; config.insert("ratios".into(), map keyed by u32)
// after
let string_keyed: BTreeMap<String, f64> = inner.into_iter().map(|(k, v)| (k.to_string(), v)).collect(); Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate config values are JSON-serializable
serde_json::to_string(&value).map_err(|e| format!("config value '{key}' not serializable: {e}"))?; Type guard
fn is_json_serializable(v: &ConfigValue) -> bool { serde_json::to_string(v).is_ok() } Try / catch
match create_importable_component(...) {
Err(e) if e.to_string().contains("Failed to serialize config value") => {
eprintln!("non-JSON config value: {e:#}");
}
Err(e) => return Err(e),
Ok(v) => v,
} Prevention
- Use only JSON-compatible types in config maps (string keys, finite floats)
- Check for NaN/Infinity in computed defaults before inserting into config
- Add a debug serialization pass over config before launching the node
When it happens
Trigger: Passing a config entry whose value cannot be JSON-serialized: a HashMap/BTreeMap with non-string keys (serde_json requires string keys for maps), a float that is NaN/Infinity (serde_json rejects them by default), or a custom type not implementing serde::Serialize in a way JSON supports.
Common situations: Users constructing a backtest node config programmatically in Rust with nested maps keyed by integers/enums; NaN appearing from computed default values; custom config structs with unsupported field types (e.g. tuple keys, non-string enum keys).
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}
- Invalid config type for AxExecutionClientFactory. Expected A
- Invalid factory address for DEX {name} on chain {chain} for
- heartbeat_secs must be positive when set
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9f2e582051206e00.
Report an issue: GitHub.