nautechsystems/nautilus_trader · error
Invalid exec algorithm params
Error message
Invalid exec algorithm params
What it means
When loading an order row, the `exec_algorithm_params` JSONB column is deserialized into `IndexMap<String, String>` and unwrapped with expect(). The panic means the JSON in that column is not an object of string-to-string pairs (wrong JSON shape or types), so the row cannot be hydrated.
Source
Thrown at crates/infrastructure/src/sql/models/orders.rs:1155
let linked_order_ids = row
.try_get::<Option<Vec<String>>, _>("linked_order_ids")
.ok()
.and_then(|ids| ids.map(|ids| ids.into_iter().map(ClientOrderId::from).collect()));
let parent_order_id = row
.try_get::<Option<&str>, _>("parent_order_id")
.ok()
.and_then(|x| x.map(ClientOrderId::from));
let exec_algorithm_id = row
.try_get::<Option<&str>, _>("exec_algorithm_id")
.ok()
.and_then(|x| x.map(ExecAlgorithmId::from));
let exec_algorithm_params: Option<IndexMap<Ustr, Ustr>> = row
.try_get::<Option<serde_json::Value>, _>("exec_algorithm_params")
.ok()
.and_then(|x| {
x.map(|x| {
serde_json::from_value::<IndexMap<String, String>>(x)
.expect("Invalid exec algorithm params")
})
})
.map(|x| {
x.into_iter()
.map(|(k, v)| (Ustr::from(k.as_str()), Ustr::from(v.as_str())))
.collect()
});
let exec_spawn_id = row
.try_get::<Option<&str>, _>("exec_spawn_id")
.ok()
.and_then(|x| x.map(ClientOrderId::from));
let tags = tags_from_row(row);
let init_id = row.try_get::<&str, _>("init_id").map(UUID4::from)?;
let ts_init = row.try_get::<String, _>("ts_init").map(UnixNanos::from)?;
let ts_last = row.try_get::<String, _>("ts_last").map(UnixNanos::from)?;
let snapshot = OrderSnapshot {
trader_id,View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the column: `SELECT id, exec_algorithm_params FROM orders WHERE jsonb_typeof(exec_algorithm_params) <> 'object'` and fix values
- Make the writer stringify all param values before storing (json values as strings)
- Cast numbers at read time by deserializing into `IndexMap<String, serde_json::Value>` and coercing, or a struct with #[serde(untyped)] handling
- Replace expect with error propagation (`?`) so one bad row doesn't abort the whole query
Example fix
// before
serde_json::from_value::<IndexMap<String, String>>(x).expect("Invalid exec algorithm params")
// after
serde_json::from_value::<IndexMap<String, serde_json::Value>>(x)
.map_err(|e| ModelError::Parse(format!("invalid exec_algorithm_params: {e}")))?
.into_iter()
.map(|(k, v)| (Ustr::from(&k), Ustr::from(&v.to_string().trim_matches('"').to_string())))
.collect() Defensive patterns
Strategy: validation
Validate before calling
fn valid_exec_params(v: Option<&serde_json::Value>) -> bool {
v.map(|v| matches!(v, serde_json::Value::Object(m)
if m.values().all(|x| matches!(x, serde_json::Value::String(_))))).unwrap_or(true)
} Type guard
fn is_string_map(v: &serde_json::Value) -> bool {
matches!(v, Value::Object(m) if m.values().all(|x| matches!(x, Value::String(_))))
} Try / catch
let params = serde_json::from_value::<IndexMap<String, String>>(x)
.map_err(|e| ModelError::Parse(format!("row {}: invalid exec_algorithm_params: {e}", row_id)))?; Prevention
- Stringify all param values before writing to JSONB
- Never hand-edit JSONB columns; use the model's writer path
- Add a JSON schema check (object of strings) at insert time
- Round-trip test exec algorithm params persistence
When it happens
Trigger: Calling `OrderModel::from_row` where `exec_algorithm_params` contains e.g. a JSON array, a nested object (`{"a": {"b": 1}}`), numeric/boolean values (`{"period": 10}` instead of `"10"`), or invalid JSON entirely.
Common situations: Custom exec-algorithm code writing params with numeric values instead of strings; manual SQL updates to the JSONB column; schema drift between nautilus versions on how params are stored.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- Invalid `OrderType`
- Invalid `OrderSide`
- Invalid `TimeInForce`
- Invalid `LiquiditySide`
- Invalid `OrderStatus`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7c674dbd270a958b.
Report an issue: GitHub.