{"record":{"id":"191b0358a42eca37","repo":"nautechsystems/nautilus_trader","slug":"canonical-result-run-must-be-an-object","errorCode":null,"errorMessage":"canonical result run must be an object","messagePattern":"canonical result run must be an object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/result.rs","lineNumber":423,"sourceCode":"        .as_array()\n        .ok_or_else(|| anyhow::anyhow!(\"canonical diagnostics must be an array\"))?;\n    for diagnostic in diagnostics {\n        let object = diagnostic\n            .as_object()\n            .ok_or_else(|| anyhow::anyhow!(\"canonical diagnostic must be an object\"))?;\n        validate_fields(object, &[\"code\"], \"canonical diagnostic\")?;\n        anyhow::ensure!(\n            object.get(\"code\").and_then(Value::as_str) == Some(\"funding-settlement-failed\"),\n            \"unsupported canonical diagnostic code\"\n        );\n    }\n    Ok(())\n}\n\nfn validate_run(value: &Value) -> anyhow::Result<()> {\n    let object = value\n        .as_object()\n        .ok_or_else(|| anyhow::anyhow!(\"canonical result run must be an object\"))?;\n    validate_fields(\n        object,\n        &[\n            \"backtest_end_ns\",\n            \"backtest_start_ns\",\n            \"iterations\",\n            \"outcome\",\n            \"run_config_id\",\n            \"total_events\",\n            \"total_orders\",\n            \"total_positions\",\n            \"trader_id\",\n        ],\n        \"canonical result run\",\n    )?;\n\n    for key in [\n        \"iterations\",","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/result.rs#L405-L441","documentation":"The 'run' section of a canonical result must be a JSON object holding the run metadata (backtest_end_ns, backtest_start_ns, iterations, outcome, run_config_id, total_events, total_orders, total_positions, trader_id). validate_run throws this when 'run' is null, an array, or any other non-object type, during both from_state construction and from_slice parsing.","triggerScenarios":"from_slice with \"run\": [] or \"run\": null; constructing a document where the run metadata was serialized as a list or omitted to null.","commonSituations":"Hand-assembled result JSON with run as an array of key/value pairs; a producer from another schema nesting run differently.","solutions":["Change run to an object containing exactly the nine required schema fields","Fix the serializer so run metadata is emitted as a JSON map","Regenerate the document with the library's canonical writer"],"exampleFix":"// before\n\"run\": []\n// after\n\"run\": {\"backtest_end_ns\": null, \"backtest_start_ns\": null, \"iterations\": \"1\", \"outcome\": \"completed\", \"run_config_id\": null, \"total_events\": \"0\", \"total_orders\": \"0\", \"total_positions\": \"0\", \"trader_id\": \"TRADER-001\"}","handlingStrategy":"validation","validationCode":"fn run_is_object(doc: &serde_json::Value) -> bool {\n    doc.get(\"run\").map_or(false, |v| v.is_object())\n}","typeGuard":"fn is_object(v: &serde_json::Value) -> bool { v.is_object() }","tryCatchPattern":"match CanonicalResult::from_slice(&bytes) {\n    Ok(result) => /* use result */,\n    Err(e) if e.to_string().contains(\"run must be an object\") => /* rebuild 'run' as an object with the nine schema fields */,\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Serialize run metadata as a JSON map with exactly the nine schema fields","Never emit null or an array for the run section","Prefer the library's from_state constructor over hand-assembling documents"],"tags":["json","type-mismatch","schema-validation"],"backgroundTag":"type-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}