{"record":{"id":"81a004d9da406d99","repo":"nautechsystems/nautilus_trader","slug":"canonical-run-field-field-is-not-a-canonical-u","errorCode":null,"errorMessage":"canonical run field '{field}' is not a canonical unsigned decimal","messagePattern":"canonical run field '(.+?)' is not a canonical unsigned decimal","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/result.rs","lineNumber":479,"sourceCode":"    );\n    anyhow::ensure!(\n        matches!(\n            object.get(\"outcome\").and_then(Value::as_str),\n            Some(\"completed\" | \"failed\" | \"incomplete\" | \"stopped\")\n        ),\n        \"unsupported canonical run outcome\"\n    );\n    Ok(())\n}\n\nfn validate_unsigned_decimal(value: &Value, field: &str, nullable: bool) -> anyhow::Result<()> {\n    if nullable && value.is_null() {\n        return Ok(());\n    }\n    let value = value\n        .as_str()\n        .ok_or_else(|| anyhow::anyhow!(\"canonical run field '{field}' must be a decimal string\"))?;\n    anyhow::ensure!(\n        value == \"0\"\n            || (!value.is_empty()\n                && !value.starts_with('0')\n                && value.bytes().all(|byte| byte.is_ascii_digit())),\n        \"canonical run field '{field}' is not a canonical unsigned decimal\"\n    );\n    Ok(())\n}\n\nfn validate_statistics(value: &Value) -> anyhow::Result<()> {\n    let object = value\n        .as_object()\n        .ok_or_else(|| anyhow::anyhow!(\"canonical result statistics must be an object\"))?;\n    validate_fields(\n        object,\n        &[\"general\", \"pnls\", \"returns\", \"returns_series\"],\n        \"canonical result statistics\",\n    )?;","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/result.rs#L461-L497","documentation":"After confirming the field is a string, `validate_unsigned_decimal` enforces canonical formatting: the value must be exactly \"0\" or a non-empty digit-only string with no leading zero. This error is thrown for strings like \"007\", \"1.5\", \"-3\", \" 12\", \"\", or \"1e3\" — i.e. non-canonical representations of unsigned decimals. This keeps the canonical document byte-stable and deterministic.","triggerScenarios":"Validating a run document whose iterations/total_events/total_orders/total_positions or backtest_start_ns/backtest_end_ns string is not a canonical unsigned decimal: leading zeros (\"042\"), floats (\"3.14\"), negatives (\"-1\"), whitespace, exponent notation, or scientific notation.","commonSituations":"Timestamps formatted with float seconds then stringified (\"1720000000.5\"); values formatted with thousands separators; numbers produced via toFixed/percent formatting; manual edits adding padding zeros; negative values from buggy counters.","solutions":["Rewrite the value in canonical form: \"0\" or digits-only with no leading zeros (e.g. \"042\" -> \"42\")","Regenerate the document with the canonical writer instead of hand-editing","Normalize the string in a pre-processing step (strip leading zeros, reject non-digit characters) before validation","Fix the producing code so it serializes integers with plain decimal formatting"],"exampleFix":"// before\n{\"run\": {\"total_orders\": \"0042\"}}\n// after\n{\"run\": {\"total_orders\": \"42\"}}","handlingStrategy":"validation","validationCode":"fn is_canonical_unsigned_decimal(s: &str) -> bool {\n    s == \"0\" || (!s.is_empty() && !s.starts_with('0') && s.bytes().all(|b| b.is_ascii_digit()))\n}","typeGuard":"fn value_is_canonical_decimal(v: &serde_json::Value) -> bool {\n    v.as_str().map_or(false, is_canonical_unsigned_decimal)\n}","tryCatchPattern":"match validate_document(&doc) {\n    Err(e) if e.to_string().contains(\"canonical unsigned decimal\") => {\n        // strip leading zeros / reformat the offending field and retry\n    }\n    other => other,\n}","preventionTips":["Format integers with plain decimal formatting (no padding, no separators, no exponents)","Never build ns-timestamp strings from float seconds","Reject or normalize non-canonical numerics at document creation time","Run the validator as part of your export pipeline to catch format drift early"],"tags":["validation","format","decimal","backtest"],"backgroundTag":"invalid-argument-format","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"}