nautechsystems/nautilus_trader · error
FX rollover acknowledgement count {}, expected {}
Error message
FX rollover acknowledgement count {}, expected {} What it means
BacktestNode's FX rollover module throws this when the number of acknowledgement outcomes supplied to `acknowledge` does not match the number of pending adjustments recorded in the completed rollover batch. Each adjustment must be explicitly acknowledged (success or failure) exactly once; a count mismatch indicates the caller returned partial or extra results from the rollover batch.
Source
Thrown at crates/backtest/src/modules/fx_rollover.rs:665
let day = day.as_mut().expect("rollover day initialized");
day.pending_adjustments = Some(batch);
day.pending_end_date = Some(batch_end_date);
day.attempt_time = Some(ts_now);
Ok(SimulationModuleResult::Completed(adjustments))
}
fn acknowledge(&self, outcomes: &[AccountAdjustmentOutcome]) -> anyhow::Result<()> {
let (adjustments, attempt_time, batch_end_date) = {
let mut day = self.rollover_day.borrow_mut();
let day = day
.as_mut()
.ok_or_else(|| anyhow::anyhow!("FX rollover day is not initialized"))?;
let adjustment_count = day
.pending_adjustments
.as_ref()
.ok_or_else(|| anyhow::anyhow!("no completed FX rollover batch to acknowledge"))?
.len();
anyhow::ensure!(
outcomes.len() == adjustment_count,
"FX rollover acknowledgement count {}, expected {}",
outcomes.len(),
adjustment_count
);
let adjustments = day
.pending_adjustments
.take()
.ok_or_else(|| anyhow::anyhow!("no completed FX rollover batch to acknowledge"))?;
(
adjustments,
day.attempt_time
.take()
.ok_or_else(|| anyhow::anyhow!("FX rollover attempt time was not recorded"))?,
day.pending_end_date.ok_or_else(|| {
anyhow::anyhow!("FX rollover batch end date was not recorded")
})?,
)View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure every pending adjustment produces exactly one outcome entry in the same order
- Check adjustment handlers for early returns that skip emitting an outcome
- Log outcomes.len() and the adjustment count to identify which instruments are missing/duplicated
- Pin module versions so rollover batch generation and acknowledgement logic stay in sync
Example fix
// before: skipping failed adjustments in outcomes let outcomes = adjustments.iter().filter(|a| a.apply().is_ok()).map(...).collect(); // after: one outcome per adjustment, including failures let outcomes = adjustments.iter().map(|a| AckOutcome::from(a.apply())).collect();
Defensive patterns
Strategy: validation
Validate before calling
assert_eq!(outcomes.len(), day.pending_adjustments.as_ref().map(|p| p.len()).unwrap_or(0), "outcome/adjustment count mismatch");
Prevention
- Emit exactly one acknowledgement outcome per pending adjustment, in order
- Include failures as outcomes rather than skipping them
- Add a debug assertion comparing counts before calling acknowledge
When it happens
Trigger: Calling `process_rollover` when the FX rollover day has a completed `pending_adjustments` batch, and the outcomes Vec passed to `acknowledge` has fewer or more entries than `pending_adjustments.len()` — e.g. an adjustment handler silently skipped an instrument or duplicated results.
Common situations: Custom rollover adjustment callbacks that return early on error without emitting an outcome; applying adjustments to a filtered subset of instruments while acknowledging all; version drift where module internals changed but acknowledgement logic was not updated.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- CFD swap acknowledgement count {}, expected {}
- FX rollover attempt time was not recorded
- FX rollover batch end date was not recorded
- Cannot handle command: {command:?}
- Latency model should be initialized
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c972fe29faa3cc75.
Report an issue: GitHub.