nautechsystems/nautilus_trader · error

CFD swap batch end date was not recorded

Error message

CFD swap batch end date was not recorded

What it means

Raised in `acknowledge` when the rollover day exists but `pending_end_date` is None, i.e. the module recorded pending adjustments but never recorded the batch's end date. Internally this indicates the two fields were not set together, so the acknowledgement cannot determine the batch period it is closing.

Source

Thrown at crates/backtest/src/modules/cfd_swap.rs:472

                .ok_or_else(|| anyhow::anyhow!("CFD swap rollover day is not initialized"))?;
            let adjustment_count = day
                .pending_adjustments
                .as_ref()
                .ok_or_else(|| anyhow::anyhow!("no completed CFD swap batch to acknowledge"))?
                .len();
            anyhow::ensure!(
                outcomes.len() == adjustment_count,
                "CFD swap acknowledgement count {}, expected {}",
                outcomes.len(),
                adjustment_count
            );
            let adjustments = day
                .pending_adjustments
                .take()
                .ok_or_else(|| anyhow::anyhow!("no completed CFD swap batch to acknowledge"))?;
            let end_date = day
                .pending_end_date
                .ok_or_else(|| anyhow::anyhow!("CFD swap batch end date was not recorded"))?;
            (adjustments, end_date)
        };

        let mut failed = Vec::new();

        for (adjustment, outcome) in adjustments.into_iter().zip(outcomes) {
            match outcome {
                AccountAdjustmentOutcome::Applied => {
                    let mut totals = self.swap_totals.borrow_mut();
                    let total = totals.entry(adjustment.amount.currency).or_default();
                    *total = total
                        .checked_add(adjustment.amount.as_decimal())
                        .ok_or_else(|| anyhow::anyhow!("CFD swap diagnostic total overflow"))?;
                }
                AccountAdjustmentOutcome::Failed(error) if error.is_retryable() => {
                    log::warn!(
                        "Cannot apply CFD swap adjustment for {} on {}: {error}",
                        adjustment.amount.currency,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the batch completion step sets both `pending_adjustments` and `pending_end_date` atomically.
  2. Treat this as a module-internal invariant break: check the version/patch level of the backtest crate and update.
  3. If restoring saved backtest state, persist and restore both fields together.
  4. Avoid calling acknowledge twice; the first ack clears pending_end_date on success.
Defensive patterns

Strategy: validation

Validate before calling

// ensure batch metadata set together before ack
anyhow::ensure!(engine.pending_batch_ready(), "pending adjustments and end date must both be set");

Try / catch

match engine.acknowledge(&outcomes) {
    Err(e) if e.to_string().contains("end date was not recorded") => {
        log::error!("module state inconsistent; rebuild module or upgrade crate");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `acknowledge` when pending_adjustments was populated through a path that skipped setting `pending_end_date`, or acknowledging a partially-initialized rollover day (day exists, batch metadata incomplete).

Common situations: Custom or modified rollover pipelines that set pending adjustments manually; deserialized/restored backtest state where the end date was not persisted; a previous successful acknowledgement cleared `pending_end_date` but a second ack still sees stale adjustments.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/55e0b7e43f9a30a3. Report an issue: GitHub.