{"record":{"id":"3e33e120daf6ace5","repo":"nautechsystems/nautilus_trader","slug":"fixed-point-scale-fits-quantityraw","errorCode":null,"errorMessage":"Fixed-point scale fits QuantityRaw","messagePattern":"Fixed-point scale fits QuantityRaw","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/types/quantity.rs","lineNumber":749,"sourceCode":"                .checked_sub(rhs.raw)\n                .expect(\"Underflow occurred when subtracting `Quantity`\"),\n            precision: self.precision.max(rhs.precision),\n        }\n    }\n}\n\nimpl Mul for Quantity {\n    type Output = Self;\n    fn mul(self, rhs: Self) -> Self::Output {\n        let result_raw = if self.raw != QUANTITY_UNDEF\n            && rhs.raw != QUANTITY_UNDEF\n            && self.precision <= FIXED_PRECISION\n            && rhs.precision <= FIXED_PRECISION\n        {\n            checked_mul_div_fixed(self.raw, rhs.raw)\n        } else {\n            let scalar = QuantityRaw::try_from(raw_scale(self.precision.min(rhs.precision)))\n                .expect(\"Fixed-point scale fits QuantityRaw\");\n            checked_mul_div_raw(self.raw, rhs.raw, scalar)\n        }\n        .filter(|raw| *raw <= QUANTITY_RAW_MAX)\n        .expect(\"Overflow occurred when multiplying `Quantity`\");\n\n        Self {\n            raw: result_raw,\n            precision: self.precision.max(rhs.precision),\n        }\n    }\n}\n\nimpl Add<Decimal> for Quantity {\n    type Output = Decimal;\n    fn add(self, rhs: Decimal) -> Self::Output {\n        self.as_decimal() + rhs\n    }\n}","sourceCodeStart":731,"sourceCodeEnd":767,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/types/quantity.rs#L731-L767","documentation":"Quantity::mul multiplies two fixed-point quantities using checked_mul_div with a scale scalar. Before scaling, the code converts raw_scale(min precision) into a QuantityRaw (u64-backed); this panic fires when that scaled value cannot fit in QuantityRaw. It is an internal invariant: for precisions <= FIXED_PRECISION the scale should always fit, so hitting this indicates an unexpectedly large precision.","triggerScenarios":"Calling Quantity::mul (the `*` operator) on two Quantity values whose precision exceeds FIXED_PRECISION, so the else branch computes raw_scale(min(precision)) and the scaled divisor overflows QuantityRaw::try_from.","commonSituations":"Quantities constructed with very high precision (e.g. from exotic instrument definitions or misparsed instrument definitions with precision above the fixed-point limit), or a bug/overflow in raw_scale for the given precision.","solutions":["Check the precision of both operands; cap them at FIXED_PRECISION before multiplying.","Verify instrument definitions (price/size precision) are correct and within supported limits.","If precision must exceed FIXED_PRECISION, use checked arithmetic or higher-width intermediates instead of relying on Quantity::mul.","Report as a bug if it fires with precision <= FIXED_PRECISION; the invariant should hold."],"exampleFix":"// before\nlet c = qty_a * qty_b; // panics if scaled raw overflows QuantityRaw\n// after\nassert!(qty_a.precision <= FIXED_PRECISION && qty_b.precision <= FIXED_PRECISION);\nlet c = qty_a * qty_b;","handlingStrategy":"validation","validationCode":"fn can_mul(a: &Quantity, b: &Quantity) -> bool {\n    a.precision <= FIXED_PRECISION\n        && b.precision <= FIXED_PRECISION\n        && a.raw.checked_mul(b.raw).map(|r| r <= QUANTITY_RAW_MAX).unwrap_or(false)\n}","typeGuard":"fn precision_in_range(q: &Quantity) -> bool { q.precision <= FIXED_PRECISION }","tryCatchPattern":"// Rust panics are not catchable via Result; use catch_unwind if absolutely required\nlet result = std::panic::catch_unwind(|| a * b);","preventionTips":["Keep quantity precisions within FIXED_PRECISION when constructing instruments","Use Quantity::new_checked for conversions from raw values","Bound operand magnitudes before multiplicative composition"],"tags":["rust","arithmetic","overflow","fixed-point"],"backgroundTag":"value-out-of-range","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"}