nautechsystems/nautilus_trader · error
no completed FX rollover batch to acknowledge
Error message
no completed FX rollover batch to acknowledge
What it means
Raised in the FX rollover module's `acknowledge` when `day.pending_adjustments` is None — there is no completed rollover batch awaiting acknowledgement. Pending adjustments are set when a batch completes and taken on acknowledgement; acknowledging without a batch is an ordering/lifecycle violation.
Source
Thrown at crates/backtest/src/modules/fx_rollover.rs:663
let adjustments = batch.iter().map(|adjustment| adjustment.amount).collect();
let mut day = self.rollover_day.borrow_mut();
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
- Only acknowledge outcomes produced by a completed rollover batch in the same processing cycle.
- Track acknowledgement state in the driver to prevent duplicate ack calls.
- If outcomes were lost, re-run the rollover batch generation instead of acking stale results.
- Check that reset/init logic is not clearing pending state between batch completion and ack.
Example fix
// before
loop {
engine.acknowledge(&outcomes)?; // retry re-acks same batch
}
// after
if !batch_acked {
engine.acknowledge(&outcomes)?;
batch_acked = true;
} Defensive patterns
Strategy: type-guard
Validate before calling
anyhow::ensure!(engine.has_pending_fx_batch(), "no completed FX rollover batch; run process_rollover first");
Type guard
fn pending_fx_batch(engine: &FxRolloverModule) -> bool { engine.has_pending_batch() } Try / catch
if let Err(e) = engine.acknowledge(&outcomes) {
if e.to_string().contains("no completed FX rollover batch") {
log::warn!("ack without batch; check driver event ordering");
} else { return Err(e); }
} Prevention
- Pair every batch completion with exactly one acknowledgement
- Never re-ack after failures; instead re-run batch generation
- Verify resets do not clear pending state between completion and ack
When it happens
Trigger: Calling `acknowledge` when no batch was completed for the day, calling it a second time for the same batch (first `take()` cleared it), or acking before `process_rollover` generated adjustments.
Common situations: Retry drivers that re-ack after failures; event pipelines delivering the ack out of order relative to batch completion; unit tests calling acknowledge directly without running the rollover pass.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- FX rollover day is not initialized
- CFD swap rollover day is not initialized
- Python SimulationModule.reset failed: {e}
- Active execution intent {intent_id} was not found
- Cannot handle command: {command:?}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5df2f314f2d379e1.
Report an issue: GitHub.