{"record":{"id":"62f9126bbe956e73","repo":"nautechsystems/nautilus_trader","slug":"serialized-position-adjustment-was-not-an-object","errorCode":null,"errorMessage":"serialized position adjustment was not an object","messagePattern":"serialized position adjustment was not an object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/result.rs","lineNumber":752,"sourceCode":"    }\n}\n\nfn patch_order_event_decimals(event: &OrderEventAny, value: &mut Value) -> anyhow::Result<()> {\n    if let OrderEventAny::Initialized(initialized) = event {\n        let payload = variant_payload_mut(value)?;\n        set_decimal(payload, \"limit_offset\", initialized.limit_offset);\n        set_decimal(payload, \"trailing_offset\", initialized.trailing_offset);\n    }\n    Ok(())\n}\n\nfn patch_position_adjustment(\n    adjustment: &PositionAdjusted,\n    value: &mut Value,\n) -> anyhow::Result<()> {\n    let object = value\n        .as_object_mut()\n        .ok_or_else(|| anyhow::anyhow!(\"serialized position adjustment was not an object\"))?;\n    set_decimal(object, \"quantity_change\", adjustment.quantity_change);\n    Ok(())\n}\n\nfn variant_payload_mut(value: &mut Value) -> anyhow::Result<&mut Map<String, Value>> {\n    let variant = value\n        .as_object_mut()\n        .and_then(|object| object.values_mut().next())\n        .and_then(Value::as_object_mut)\n        .ok_or_else(|| anyhow::anyhow!(\"serialized enum variant was not an object\"))?;\n    Ok(variant)\n}\n\nfn canonical_value<T: Serialize>(source: &T) -> anyhow::Result<Value> {\n    let mut value = serde_json::to_value(source)?;\n    canonicalize_value(&mut value)?;\n    Ok(value)\n}","sourceCodeStart":734,"sourceCodeEnd":770,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/result.rs#L734-L770","documentation":"Raised by `patch_position_adjustment` when the JSON produced from a `PositionAdjusted` event is not a JSON object (`Value::Object`), so its `quantity_change` key cannot be patched with a stringified decimal. The canonicalizer expects every serialized position-adjustment event to deserialize into a map; array/string/number encodings indicate the event type's serde shape changed.","triggerScenarios":"Canonicalizing a `PositionAdjusted` event whose `serde_json::to_value` yields a non-object — e.g. a newtype/enum variant serialized as an array or tuple because the struct gained tuple representation, or a custom `Serialize` impl emitting a bare string.","commonSituations":"Domain event structs changed from struct variants to tuple variants in an enum; developers adding fields to `PositionAdjusted` while switching its serde representation; stale fixtures from an older schema.","solutions":["Keep `PositionAdjusted` serialized as a JSON object (struct or externally-tagged struct variant), not a tuple/newtype variant.","Inspect the produced JSON with `serde_json::to_string_pretty` to see the actual shape.","Update `patch_position_adjustment` if the representation legitimately changed, adjusting how it descends into the variant payload (use `variant_payload_mut`).","Rebuild and rerun backtest result tests to refresh golden fixtures."],"exampleFix":"// before: PositionAdjusted(Quantity)  // serializes to a bare number\n// after:\n#[derive(Serialize)]\nstruct PositionAdjusted { quantity_change: Quantity }","handlingStrategy":"type-guard","validationCode":"let v = serde_json::to_value(&event)?;\nassert!(v.is_object(), \"PositionAdjusted must serialize to an object\");","typeGuard":"fn is_object(v: &serde_json::Value) -> bool { v.is_object() }","tryCatchPattern":null,"preventionTips":["Keep event types as struct variants with named fields.","Dump serialized events to JSON in unit tests to catch representation drift early."],"tags":["serialization","json","backtest"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}