{"record":{"id":"bf5ea9a185f058d1","repo":"nautechsystems/nautilus_trader","slug":"canonical-component-field-key-must-contain-str","errorCode":null,"errorMessage":"canonical component field '{key}' must contain strings","messagePattern":"canonical component field '(.+?)' must contain strings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/result.rs","lineNumber":391,"sourceCode":"        .as_object()\n        .ok_or_else(|| anyhow::anyhow!(\"canonical result components must be an object\"))?;\n    validate_fields(\n        object,\n        &[\n            \"actor_ids\",\n            \"exec_algorithm_ids\",\n            \"strategy_ids\",\n            \"trader_state\",\n        ],\n        \"canonical result components\",\n    )?;\n\n    for key in [\"actor_ids\", \"exec_algorithm_ids\", \"strategy_ids\"] {\n        let values = object\n            .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()","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/result.rs#L373-L409","documentation":"After confirming the component ID fields are arrays, validate_components requires every element of actor_ids, exec_algorithm_ids, and strategy_ids to be a JSON string. Any number, boolean, null, or nested value inside these arrays triggers this error.","triggerScenarios":"from_slice with e.g. \"strategy_ids\": [1, 2] or [null]; constructing a document from component collections containing numeric or non-string IDs.","commonSituations":"Numeric component IDs from an external system serialized as numbers; a null sneaking into a list during assembly.","solutions":["Convert each element to a string (e.g. id.to_string()) before serializing","Filter or fix null/non-string entries in the ID collections","Fix the producer so component IDs are stored as strings end-to-end"],"exampleFix":"// before\n\"strategy_ids\": [1, 2]\n// after\n\"strategy_ids\": [\"1\", \"2\"]","handlingStrategy":"validation","validationCode":"fn component_ids_are_strings(c: &serde_json::Value) -> bool {\n    [\"actor_ids\", \"exec_algorithm_ids\", \"strategy_ids\"].iter().all(|k| {\n        c.get(k).and_then(|v| v.as_array()).map_or(false, |a| a.iter().all(|x| x.is_string()))\n    })\n}","typeGuard":"fn all_strings(a: &[serde_json::Value]) -> bool { a.iter().all(|x| x.is_string()) }","tryCatchPattern":"match CanonicalResult::from_slice(&bytes) {\n    Ok(result) => /* use result */,\n    Err(e) if e.to_string().contains(\"must contain strings\") => /* stringify array elements and retry */,\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Store component IDs as strings from the source system onward","Call .to_string() on numeric IDs before serialization","Filter nulls from ID collections before building the document"],"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"}