{"record":{"id":"1f8736a6370429ac","repo":"nautechsystems/nautilus_trader","slug":"canonical-backtest-result-must-be-a-json-object","errorCode":null,"errorMessage":"canonical backtest result must be a JSON object","messagePattern":"canonical backtest result must be a JSON object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/result.rs","lineNumber":307,"sourceCode":"                \"total_orders\": state.total_orders.to_string(),\n                \"total_positions\": state.total_positions.to_string(),\n                \"trader_id\": state.trader_id,\n            },\n            \"schema\": CANONICAL_SCHEMA,\n            \"statistics\": canonical_statistics(state.statistics),\n            \"summary\": state.summary,\n        });\n\n        canonicalize_document(&mut document)?;\n        validate_document(&document)?;\n        Ok(Self { document })\n    }\n}\n\nfn validate_document(document: &Value) -> anyhow::Result<()> {\n    let object = document\n        .as_object()\n        .ok_or_else(|| anyhow::anyhow!(\"canonical backtest result must be a JSON object\"))?;\n    anyhow::ensure!(\n        object.get(\"schema\").and_then(Value::as_str) == Some(CANONICAL_SCHEMA),\n        \"unsupported canonical backtest result schema\"\n    );\n    let fields = [\n        \"accounts\",\n        \"components\",\n        \"diagnostics\",\n        \"fills\",\n        \"orders\",\n        \"portfolio_snapshots\",\n        \"position_snapshots\",\n        \"positions\",\n        \"run\",\n        \"schema\",\n        \"statistics\",\n        \"summary\",\n    ];","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/result.rs#L289-L325","documentation":"`validate_document` (used by both `from_slice` and `from_state`) first requires the canonical backtest result document to be a JSON object at the top level. If the parsed value is an array, string, number, or null, this error is returned before any schema checks.","triggerScenarios":"Calling `from_slice` with a JSON array (e.g. a list of results), a bare string/number, or null bytes serialized as JSON; calling `from_state` after serializing something other than the result object.","commonSituations":"Wrapping multiple results in a `[...]` array for batch runs; saving only the `results` inner value or a summary string instead of the whole document; a producer bug that serialized the wrong value.","solutions":["Ensure the top-level value is a single JSON object containing `schema`, `accounts`, `components`, etc.","Unwrap any enclosing array and pass the individual result object","Regenerate the document with the library's result writer to guarantee the correct top-level shape","Check the producer code — if it saved the wrong level of the structure, fix the serialization call"],"exampleFix":"// before\nlet bytes = br#\"[{\"schema\":\"...\"}]\"#; // array\nBacktestResult::from_slice(bytes)?;\n// after\nlet bytes = br#\"{\"schema\":\"...\",\"accounts\":[],...}\"#; // object\nBacktestResult::from_slice(bytes)?;","handlingStrategy":"type-guard","validationCode":"import json\ndoc = json.load(open(path))\nassert isinstance(doc, dict), \"result must be a top-level JSON object\"","typeGuard":"fn is_json_object(v: &serde_json::Value) -> bool { v.is_object() }","tryCatchPattern":"match BacktestResult::from_slice(&bytes) {\n    Err(e) if e.to_string().contains(\"must be a JSON object\") => {\n        eprintln!(\"unexpected top-level JSON type: {e:#}\");\n    }\n    Err(e) => return Err(e),\n    Ok(r) => r,\n}","preventionTips":["Always serialize the whole result document, not an inner field or wrapper array","Type-check the top-level value with `Value::is_object()` before calling from_slice"],"tags":["json","schema","backtest","validation"],"backgroundTag":"schema-validation-failed","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"}