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
- Ensure the batch completion step sets both `pending_adjustments` and `pending_end_date` atomically.
- Treat this as a module-internal invariant break: check the version/patch level of the backtest crate and update.
- If restoring saved backtest state, persist and restore both fields together.
- 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
- Do not manually construct or mutate rollover day internals
- Persist and restore both pending_adjustments and pending_end_date together
- Keep the backtest crate up to date
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
- cannot calculate CFD swap for {instrument_id}: midpoint over
- cannot calculate CFD swap for position {}: adjustment overfl
- cannot calculate CFD swap for position {}: currency conversi
- CFD swap rollover day is not initialized
- no completed CFD swap batch to acknowledge
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/55e0b7e43f9a30a3.
Report an issue: GitHub.