{"record":{"id":"51f834192ee9640c","repo":"nautechsystems/nautilus_trader","slug":"invalid-fixed-point-raw-value-raw-for-precision","errorCode":null,"errorMessage":"Invalid fixed-point raw value {raw} for precision {precision}: remainder {remainder} when divided by scale {scale}. Raw value should be a multiple of {scale}. This indicates data corruption or incorrect precision/scaling upstream","messagePattern":"Invalid fixed-point raw value (.+?) for precision (.+?): remainder (.+?) when divided by scale (.+?)\\. Raw value should be a multiple of (.+?)\\. This indicates data corruption or incorrect precision/scaling upstream","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/model/src/types/fixed.rs","lineNumber":408,"sourceCode":"    #[cfg(not(feature = \"defi\"))]\n    debug_assert!(\n        precision <= FIXED_PRECISION,\n        \"precision {precision} exceeds FIXED_PRECISION {FIXED_PRECISION}: \\\n         raw value validation is not possible at this precision\"\n    );\n\n    precision >= FIXED_PRECISION\n}\n\n/// Builds the error for invalid fixed-point raw values (cold path).\n#[cold]\nfn invalid_raw_error(\n    raw: impl Display,\n    precision: u8,\n    remainder: impl Display,\n    scale: impl Display,\n) -> anyhow::Error {\n    anyhow::anyhow!(\n        \"Invalid fixed-point raw value {raw} for precision {precision}: \\\n         remainder {remainder} when divided by scale {scale}. \\\n         Raw value should be a multiple of {scale}. \\\n         This indicates data corruption or incorrect precision/scaling upstream\"\n    )\n}\n\n/// Checks that a raw unsigned fixed-point value has no spurious bits beyond the precision scale.\n///\n/// For a given precision P where P < `FIXED_PRECISION`, valid raw values must be exact\n/// multiples of `10^(FIXED_PRECISION` - P). Any non-zero remainder indicates data corruption\n/// or incorrect scaling upstream.\n///\n/// # Precision Limits\n///\n/// This check only validates when `precision < FIXED_PRECISION`:\n/// - When `precision == FIXED_PRECISION`, every bit of the raw value is significant and\n///   the check passes trivially (no \"extra\" bits to validate).","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/types/fixed.rs#L390-L426","documentation":"Nautilus fixed-point types store values as raw integers that must be exact multiples of 10^scale for the declared precision. When a validity check (`check_fixed_raw_u128/u64/i128/i64`) finds the raw value has a non-zero remainder after division by the scale factor, the value cannot be represented exactly and this error is thrown, explicitly flagging data corruption or an upstream precision/scaling mistake rather than silently truncating.","triggerScenarios":"Constructing a fixed-point type (Price, Quantity, Money, etc.) from a raw integer whose last digits are not zero-filled to the scale — e.g. building `Price` from raw=1234567 with precision 2/scale 100 — or reading such a value from corrupted data, wrong endianness decoding, or multiplying a raw value without rescaling.","commonSituations":"Feeding raw exchange integers with more decimal digits than the declared precision; manual arithmetic on `.raw` values that breaks the fixed-point invariant; deserializing data written with a different precision; scaling errors when converting floats to raw via the wrong factor (x1000 vs x100).","solutions":["Fix the source of the raw value: scale it to the declared precision (multiply/divide by the correct power of 10) before constructing the fixed-point type.","Verify the precision passed to the constructor matches the data's actual decimal places; do not force a smaller precision onto finer-grained data.","If reading persisted data, check whether it was written with a different precision and re-migrate the data.","Audit any manual `.raw` arithmetic in your code and use the domain type constructors/`Decimal` conversions instead."],"exampleFix":"// before\nlet price = Price::new_checked(raw_int, 2)?; // raw_int = 1234567, not a multiple of 100\n\n// after\nlet scaled = raw_int / 1000 * 100; // or rescale correctly upstream\nlet price = Price::new_checked(scaled, 2)?;","handlingStrategy":"validation","validationCode":"def raw_is_exact(raw: int, precision: int) -> bool:\n    scale = 10 ** precision\n    return raw % scale == 0","typeGuard":null,"tryCatchPattern":"try:\n    price = Price::new_checked(raw, precision)\nexcept Exception:\n    # rescale or reject the raw value before retrying\n    raise","preventionTips":["Never perform manual arithmetic on .raw values without rescaling","Confirm exchange data's decimal places match the declared precision","Use Decimal/domain constructors instead of raw integer math","Validate raw values against the fixed-point invariant at ingestion boundaries"],"tags":["fixed-point","precision","data-corruption","invariant"],"backgroundTag":"internal-invariant-violation","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"}