nautechsystems/nautilus_trader · error
serialized order did not contain an object core
Error message
serialized order did not contain an object core
What it means
`canonical_order` serializes an OrderAny to JSON, locates its variant payload, and expects an inner `core` object containing the order's shared fields. This internal error is thrown when the serialized JSON has no `core` object inside the variant payload — meaning the serde representation of the order does not match the expected internally-tagged shape. It is an invariant violation rather than user input validation.
Source
Thrown at crates/backtest/src/result.rs:522
}
anyhow::ensure!(
object.get("returns_series").is_some_and(Value::is_array),
"canonical returns series must be an array"
);
Ok(())
}
fn optional_nanos(value: Option<UnixNanos>) -> Value {
value.map_or(Value::Null, |nanos| Value::String(nanos.to_string()))
}
fn canonical_order(order: &OrderAny) -> anyhow::Result<Value> {
let mut value = serde_json::to_value(order)?;
let payload = variant_payload_mut(&mut value)?;
let core = payload
.get_mut("core")
.and_then(Value::as_object_mut)
.ok_or_else(|| anyhow::anyhow!("serialized order did not contain an object core"))?;
set_decimal(core, "avg_px", order.avg_px());
set_decimal(core, "slippage", order.slippage());
if let Some(events) = core.get_mut("events").and_then(Value::as_array_mut) {
for (source, encoded) in order.events().into_iter().zip(events) {
patch_order_event_decimals(source, encoded)?;
}
}
set_decimal_if_present(payload, "limit_offset", order.limit_offset());
set_decimal_if_present(payload, "trailing_offset", order.trailing_offset());
canonicalize_value(&mut value)?;
Ok(value)
}
fn canonical_fills(orders: &[OrderAny]) -> anyhow::Result<Vec<Value>> {
let mut fills = Vec::new();
for order in orders {View on GitHub (pinned to 18893faf8b)
Solutions
- Regenerate/serialize the order with the matching library version so the variant payload contains a `core` object
- Check for version mismatch between the crate that constructed the order and the one canonicalizing it
- Inspect the serde representation (serde_json::to_value(order)) to confirm the expected tagged shape
- Avoid custom serialization wrappers around OrderAny before canonicalization
Example fix
// before (drifted serde shape)
{"order": {"limit": {"avg_px": 1.0, ...}}} // no core
// after (expected shape)
{"order": {"limit": {"core": {"avg_px": "1.0", ...}}}} Defensive patterns
Strategy: try-catch
Validate before calling
fn order_core_present(order: &OrderAny) -> anyhow::Result<bool> {
let value = serde_json::to_value(order)?;
Ok(value
.get("order")
.or_else(|| value.get("limit").or_else(|| value.get("market"))
.map(|_| &value).unwrap_or(&value))
.pointer("/core")
.map_or(false, serde_json::Value::is_object))
} Type guard
fn has_object_core(payload: &serde_json::Value) -> bool {
payload.get("core").map_or(false, serde_json::Value::is_object)
} Try / catch
let canonical = canonical_order(&order).map_err(|e| {
if e.to_string().contains("did not contain an object core") {
// log serde representation and crate versions for diagnosis
}
e
})?; Prevention
- Keep order-construction and result-canonicalization crates on the same version
- Do not wrap or re-tag OrderAny serialization with custom impls
- Add a round-trip test: serialize an order of every variant and canonicalize it
- Assert the expected tagged serde shape in CI
When it happens
Trigger: Calling canonical_order (during canonical result document generation) with an OrderAny whose serde JSON lacks a `core` object in its variant payload — e.g. after a serde representation change of the order enum, a custom/foreign order variant, or tampered serialization.
Common situations: Mixing order types from a different nautilus version (serde format drift); a custom OrderAny payload that bypasses the standard order core; generated JSON wrapped or transformed by an intermediate layer that renamed `core`.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- serialized position was not an object
- Failed to serialize config value: {e}
- serialized position did not contain its identifier
- serialized position adjustment was not an object
- Failed to serialize exec algorithm params: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b728adc1c5e51aa2.
Report an issue: GitHub.