{"record":{"id":"90346c8be45777b8","repo":"nautechsystems/nautilus_trader","slug":"no-completed-cfd-swap-batch-to-acknowledge","errorCode":null,"errorMessage":"no completed CFD swap batch to acknowledge","messagePattern":"no completed CFD swap batch to acknowledge","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/modules/cfd_swap.rs","lineNumber":458,"sourceCode":"        let mut day = self.rollover_day.borrow_mut();\n        let day = day\n            .as_mut()\n            .ok_or_else(|| anyhow::anyhow!(\"CFD swap rollover day is not initialized\"))?;\n        day.pending_adjustments = Some(batch);\n        day.pending_end_date = Some(batch_end_date);\n        Ok(SimulationModuleResult::Completed(adjustments))\n    }\n\n    fn acknowledge(&self, outcomes: &[AccountAdjustmentOutcome]) -> anyhow::Result<()> {\n        let (adjustments, 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!(\"CFD swap rollover day is not initialized\"))?;\n            let adjustment_count = day\n                .pending_adjustments\n                .as_ref()\n                .ok_or_else(|| anyhow::anyhow!(\"no completed CFD swap batch to acknowledge\"))?\n                .len();\n            anyhow::ensure!(\n                outcomes.len() == adjustment_count,\n                \"CFD swap 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 CFD swap batch to acknowledge\"))?;\n            let end_date = day\n                .pending_end_date\n                .ok_or_else(|| anyhow::anyhow!(\"CFD swap batch end date was not recorded\"))?;\n            (adjustments, end_date)\n        };\n\n        let mut failed = Vec::new();","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/modules/cfd_swap.rs#L440-L476","documentation":"acknowledge() requires that a completed batch of pending adjustments exists to match the supplied outcomes against. If rollover_day exists but pending_adjustments is None, there is no completed batch to acknowledge and this error is thrown.","triggerScenarios":"Calling acknowledge() either before any process() returned Completed, or a second time after the first acknowledge consumed pending_adjustments, or with outcomes for a batch that was never produced.","commonSituations":"Retry logic re-acknowledging the same batch; engine event ordering delivering acknowledge before the module's process completed; tests acknowledging with fabricated outcomes without running process first.","solutions":["Acknowledge exactly once per Completed result from process()","Track batch lifecycle in your engine wrapper: only call acknowledge when the preceding process returned Completed","If retrying after a failure, re-run process() to regenerate the batch before acknowledging"],"exampleFix":"// before: double acknowledge\nmodule.acknowledge(&outcomes)?;\nmodule.acknowledge(&outcomes)?; // pending already consumed\n// after\nmodule.acknowledge(&outcomes)?; // once per Completed batch","handlingStrategy":"validation","validationCode":"// guard: only acknowledge a batch you actually received\nlet batch: Option<Vec<Money>> = match module.process(ts_now)? {\n    SimulationModuleResult::Completed(a) => Some(a),\n    _ => None,\n};\nif let Some(amounts) = batch { /* acknowledge */ }","typeGuard":"fn batch_ready(r: &SimulationModuleResult) -> Option<&[Money]> {\n    match r { SimulationModuleResult::Completed(a) => Some(a), _ => None }\n}","tryCatchPattern":"match module.acknowledge(&outcomes) {\n    Err(e) if e.to_string().contains(\"no completed CFD swap batch\") => {\n        log::warn!(\"acknowledge called without a completed batch\");\n        Ok(())\n    }\n    other => other,\n}","preventionTips":["One acknowledge per Completed batch; never retry-acknowledge without re-running process","Sequence engine events so acknowledge cannot arrive before process completes","In tests, always run process before acknowledge"],"tags":["backtest","cfd","acknowledgement","state-management"],"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"}