{"record":{"id":"e65ffc809039b948","repo":"nautechsystems/nautilus_trader","slug":"canonical-diagnostics-must-be-an-array","errorCode":null,"errorMessage":"canonical diagnostics must be an array","messagePattern":"canonical diagnostics must be an array","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/result.rs","lineNumber":406,"sourceCode":"            .get(key)\n            .and_then(Value::as_array)\n            .ok_or_else(|| anyhow::anyhow!(\"canonical component field '{key}' must be an array\"))?;\n        anyhow::ensure!(\n            values.iter().all(Value::is_string),\n            \"canonical component field '{key}' must contain strings\"\n        );\n    }\n    anyhow::ensure!(\n        object.get(\"trader_state\").is_some_and(Value::is_string),\n        \"canonical trader state must be a string\"\n    );\n    Ok(())\n}\n\nfn validate_diagnostics(value: &Value) -> anyhow::Result<()> {\n    let diagnostics = value\n        .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(","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/result.rs#L388-L424","documentation":"The 'diagnostics' section of a canonical result must be a JSON array (possibly empty). This error is thrown when the value is an object, string, null, or other non-array type. Enforced by validate_diagnostics during both document construction and parsing.","triggerScenarios":"from_slice with \"diagnostics\": {} or \"diagnostics\": null; constructing a document whose diagnostics value is not a list.","commonSituations":"Hand-assembled JSON emitting diagnostics as an object keyed by code; a producer omitting the field to null when there are no diagnostics.","solutions":["Change diagnostics to an array, using [] when there are no diagnostics","Fix the producer/serializer so diagnostics are always collected into a list","Regenerate the document with the library's canonical writer"],"exampleFix":"// before\n\"diagnostics\": null\n// after\n\"diagnostics\": []","handlingStrategy":"validation","validationCode":"fn diagnostics_is_array(doc: &serde_json::Value) -> bool {\n    doc.get(\"diagnostics\").map_or(false, |v| v.is_array())\n}","typeGuard":"fn is_array(v: &serde_json::Value) -> bool { v.is_array() }","tryCatchPattern":"match CanonicalResult::from_slice(&bytes) {\n    Ok(result) => /* use result */,\n    Err(e) if e.to_string().contains(\"diagnostics must be an array\") => /* convert diagnostics to an array */,\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Always collect diagnostics into a Vec/array, using [] when empty","Never emit null for empty collections in canonical documents","Regenerate documents via the library's writer"],"tags":["json","type-mismatch","arrays"],"backgroundTag":"type-mismatch","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"}