{"record":{"id":"9466e4ef87255234","repo":"nautechsystems/nautilus_trader","slug":"fill-raw-bounds-pre-checked","errorCode":null,"errorMessage":"fill raw bounds pre-checked","messagePattern":"fill raw bounds pre-checked","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/orders/mod.rs","lineNumber":1269,"sourceCode":"        if event.reconciliation && !self.filled_qty.is_zero() && event.quantity == self.filled_qty {\n            self.status = OrderStatus::Filled;\n            self.ts_closed = Some(event.ts_event);\n        }\n\n        if let Some(venue_order_id) = &event.venue_order_id\n            && (self.venue_order_id.is_none()\n                || venue_order_id != self.venue_order_id.as_ref().unwrap())\n        {\n            self.venue_order_id = Some(*venue_order_id);\n            self.venue_order_ids.push(*venue_order_id);\n        }\n\n        self.is_quote_quantity = event.is_quote_quantity;\n    }\n\n    fn filled(&mut self, event: &OrderFilled, source_status: OrderStatus) {\n        let raw = checked_quantity_raw_sum(self.filled_qty.raw, event.last_qty.raw)\n            .expect(\"fill raw bounds pre-checked\");\n        let new_filled_qty = Quantity::from_raw(raw, self.filled_qty.precision);\n\n        // Calculate overfill if any\n        if new_filled_qty > self.quantity {\n            let overfill_raw = new_filled_qty.raw - self.quantity.raw;\n            self.overfill_qty = quantity_from_domain_raw(\n                self.overfill_qty.raw.saturating_add(overfill_raw),\n                self.filled_qty.precision,\n            );\n        }\n\n        let new_leaves_qty = self.leaves_qty.saturating_sub(event.last_qty);\n\n        if new_filled_qty >= self.quantity {\n            self.status = OrderStatus::Filled;\n            self.ts_closed = Some(event.ts_event);\n        } else if new_leaves_qty.is_zero() && !self.voided_qty.is_zero() {\n            self.status = OrderStatus::Voided;","sourceCodeStart":1251,"sourceCodeEnd":1287,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/orders/mod.rs#L1251-L1287","documentation":"When applying an OrderFilled event, filled() sums the raw quantity values with checked_quantity_quantity_raw_sum and unwraps the result, asserting the raw bounds were validated earlier in the fill path (quantity can't exceed raw u64 bounds at the order's precision). If the check fails here, an upstream pre-check was skipped or the fill is pathological.","triggerScenarios":"Applying an OrderFilled whose last_qty, added to the running filled_qty, overflows/underflows the raw fixed-precision bounds — i.e. a fill not pre-validated against the order quantity.","commonSituations":"Feeding synthetic or replayed fill events with quantities beyond the order's size; venue backfill producing fills exceeding total quantity at extreme precision; custom event replay code bypassing the normal fill validation.","solutions":["Validate each fill's last_qty against the remaining quantity (leaves_qty) before applying the OrderFilled event","Use try_from / checked arithmetic when constructing events from external venue data","For replay, use the library's replay/adjustment APIs (e.g. apply adjustment paths) rather than direct event application with unvalidated quantities"],"exampleFix":"// before\norder.apply(event); // OrderFilled with unvalidated qty\n// after\nif event.last_qty > order.leaves_qty() {\n    // clamp, reject, or log the anomalous fill\n    return;\n}\norder.apply(event);","handlingStrategy":"validation","validationCode":"// Rust: before applying OrderFilled\nassert!(event.last_qty <= order.leaves_qty(), \"fill exceeds remaining quantity\");\norder.apply(event);","typeGuard":"fn fill_valid(o: &dyn Order, ev: &OrderFilled) -> bool { ev.last_qty <= o.leaves_qty() }","tryCatchPattern":null,"preventionTips":["Validate venue fills against remaining quantity before applying","Use checked constructors when converting external quantities to Quantity","Route anomalous fills to reconciliation instead of direct application"],"tags":["rust","panic","overflow","quantity"],"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"}