{"record":{"id":"e51e16e730345ee8","repo":"nautechsystems/nautilus_trader","slug":"cfd-swap-acknowledgement-count-expected","errorCode":null,"errorMessage":"CFD swap acknowledgement count {}, expected {}","messagePattern":"CFD swap acknowledgement count (.+?), expected (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/modules/cfd_swap.rs","lineNumber":460,"sourceCode":"            .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();\n\n        for (adjustment, outcome) in adjustments.into_iter().zip(outcomes) {","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/modules/cfd_swap.rs#L442-L478","documentation":"This error is raised in the CFD swap module's `acknowledge` method when the number of account adjustment outcomes passed back by the caller does not match the number of pending swap adjustments recorded when the rollover batch completed. The backtest module requires a one-to-one acknowledgement of every adjustment it applied. A count mismatch means the driver loop submitted an outcome vector that does not correspond to the current batch.","triggerScenarios":"Calling `acknowledge` with an `outcomes` slice whose length differs from `day.pending_adjustments.len()`. Typically happens when outcomes are collected across multiple days, filtered (e.g. dropping failed adjustments), duplicated, or `acknowledge` is called twice for one batch.","commonSituations":"Backtest drivers that pre-allocate or truncate outcome vectors, or that batch acknowledgements after retry loops which skip some outcomes. Also occurs if `begin_rollover`/batch completion was re-run between generating outcomes and acknowledging them, replacing the pending batch.","solutions":["Ensure the caller collects exactly one AccountAdjustmentOutcome per pending adjustment in the same order the adjustments were generated.","Call `acknowledge` exactly once per completed swap batch; do not re-call after a partial acknowledgement.","If filtering outcomes, keep placeholders (e.g. Failed outcomes) rather than removing entries so the count stays aligned.","Log both lengths (outcomes.len() and the pending count) at the call site to identify where the divergence occurs."],"exampleFix":"// before\nlet outcomes: Vec<_> = results.into_iter().filter(|r| r.is_ok()).collect();\nengine.acknowledge(&outcomes)?;\n\n// after\nlet outcomes: Vec<_> = results.into_iter().collect(); // keep 1:1 with adjustments\nengine.acknowledge(&outcomes)?;","handlingStrategy":"validation","validationCode":"let pending_count = engine.pending_adjustment_count()?;\nanyhow::ensure!(outcomes.len() == pending_count, \"outcome count {} != pending {}\", outcomes.len(), pending_count);\nengine.acknowledge(&outcomes)?;","typeGuard":null,"tryCatchPattern":"match engine.acknowledge(&outcomes) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"acknowledgement count\") => log::error!(\"outcome/batch misalignment: {e}\"),\n    Err(e) => return Err(e),\n}","preventionTips":["Keep outcomes and adjustments strictly 1:1 and in order","Never filter outcome vectors before acknowledgement","Acknowledge each batch exactly once"],"tags":["backtest","cfd","state-consistency"],"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-14T05:17:10.506Z"}