{"record":{"id":"90f06abe3a7699ca","repo":"nautechsystems/nautilus_trader","slug":"fx-rollover-day-is-not-initialized","errorCode":null,"errorMessage":"FX rollover day is not initialized","messagePattern":"FX rollover day is not initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/modules/fx_rollover.rs","lineNumber":659,"sourceCode":"            }\n            booking_date = next;\n        };\n\n        let adjustments = batch.iter().map(|adjustment| adjustment.amount).collect();\n        let mut day = self.rollover_day.borrow_mut();\n        let day = day.as_mut().expect(\"rollover day initialized\");\n        day.pending_adjustments = Some(batch);\n        day.pending_end_date = Some(batch_end_date);\n        day.attempt_time = Some(ts_now);\n        Ok(SimulationModuleResult::Completed(adjustments))\n    }\n\n    fn acknowledge(&self, outcomes: &[AccountAdjustmentOutcome]) -> anyhow::Result<()> {\n        let (adjustments, attempt_time, batch_end_date) = {\n            let mut day = self.rollover_day.borrow_mut();\n            let day = day\n                .as_mut()\n                .ok_or_else(|| anyhow::anyhow!(\"FX rollover day is not initialized\"))?;\n            let adjustment_count = day\n                .pending_adjustments\n                .as_ref()\n                .ok_or_else(|| anyhow::anyhow!(\"no completed FX rollover batch to acknowledge\"))?\n                .len();\n            anyhow::ensure!(\n                outcomes.len() == adjustment_count,\n                \"FX rollover acknowledgement count {}, expected {}\",\n                outcomes.len(),\n                adjustment_count\n            );\n            let adjustments = day\n                .pending_adjustments\n                .take()\n                .ok_or_else(|| anyhow::anyhow!(\"no completed FX rollover batch to acknowledge\"))?;\n            (\n                adjustments,\n                day.attempt_time","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/modules/fx_rollover.rs#L641-L677","documentation":"Raised in the FX rollover module's `acknowledge` (invoked via `process_rollover`) when `self.rollover_day` is None, meaning no rollover day was initialized for the current processing step. Acknowledging outcomes requires an active rollover day holding the pending adjustments batch.","triggerScenarios":"Calling `acknowledge` before the day's rollover was started; acknowledging twice (the first ack consumes the rollover day); running `process_rollover`'s ack phase on a module that never had its day state set.","commonSituations":"Event-driven drivers where the ack callback fires on days without rollover; tests constructing the module and calling process/ack out of order; reset or re-init between batch generation and acknowledgement.","solutions":["Initialize the rollover day (the module's begin/prepare step) before the acknowledgement phase runs.","Acknowledge once per rollover day only; guard the driver against duplicate ack callbacks.","Verify the driver only routes ack events for days where a rollover batch was actually processed."],"exampleFix":"// before\non_ack(|| engine.acknowledge(&outcomes)?);\n\n// after\nif engine.rollover_active() {\n    on_ack(|| engine.acknowledge(&outcomes)?);\n}","handlingStrategy":"type-guard","validationCode":"anyhow::ensure!(engine.rollover_day_initialized(), \"FX rollover day must be initialized before acknowledge\");","typeGuard":"fn fx_ack_ready(engine: &FxRolloverModule) -> bool { engine.rollover_day_initialized() }","tryCatchPattern":"match engine.acknowledge(&outcomes) {\n    Err(e) if e.to_string().contains(\"FX rollover day is not initialized\") => {\n        log::warn!(\"duplicate or out-of-order ack ignored\");\n    }\n    other => other?,\n}","preventionTips":["Initialize rollover day state each processing day before any ack","Acknowledge once per rollover batch","Route ack callbacks only for days where a rollover was processed"],"tags":["backtest","fx","lifecycle"],"backgroundTag":"invalid-state-transition","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"}