nautechsystems/nautilus_trader · error · anyhow::Error

AX fills pagination returned

Error message

AX fills pagination returned {} unique rows, expected {total_count}

What it means

At the end of pagination, if the server reported a total_count, the number of unique fills collected across all pages must equal it exactly. A shortfall means pages were missed or rows vanished mid-read, so the client aborts instead of returning an incomplete fill list.

Solutions

  1. Re-run the full pagination and compare; a transient concurrent mutation usually resolves.
  2. Pin the query to a bounded, past time window so rows cannot disappear mid-read.
  3. Log per-page lengths and the total_count to identify which page lost rows, then report to the AX backend team.
  4. If fills are mutable by design, switch to an incremental/streaming fills feed rather than snapshot pagination.

Example fix

// before: live window, rows can vanish mid-pagination
let params = FillsParams { start: Some(start), ..Default::default() };
// after: closed snapshot window
let params = FillsParams { start: Some(start), end: Some(end), ..Default::default() };
Defensive patterns

Strategy: retry

Try / catch

match client.paginate_fills(params).await {
    Ok(fills) => apply(fills),
    Err(e) if e.to_string().contains("expected {total_count}") || e.to_string().contains("unique rows, expected") => {
        warn!("incomplete fills snapshot; retrying once");
        client.paginate_fills(params).await
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Pagination loop ended (next_cursor None) with fewer unique fills than the total_count reported on the first page — e.g. a page was truncated, or fills were deleted between page requests.

Common situations: Concurrent deletes/reconciliation removing fills while reading; a silently truncated final page; server counts rows before a filter the client-side window applies.

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/eb56501c9fc1bd52. Report an issue: GitHub.

Appendix: source

Thrown at crates/adapters/architect_ax/src/http/client.rs:2295

                        !next_cursor.is_empty(),
                        "AX fills returned an empty next_cursor"
                    );
                    anyhow::ensure!(
                        page_len > 0,
                        "AX fills returned an empty page with a next_cursor"
                    );
                    anyhow::ensure!(
                        seen_cursors.insert(next_cursor.clone()),
                        "AX fills pagination repeated cursor {next_cursor:?}"
                    );
                    params.cursor = Some(next_cursor);
                }
                None => break,
            }
        }

        if let Some(total_count) = expected_total {
            anyhow::ensure!(
                fills.len() as i64 == total_count,
                "AX fills pagination returned {} unique rows, expected {total_count}",
                fills.len()
            );
        }

        let ts_init = self.generate_ts_init();
        let mut reports = Vec::with_capacity(fills.len());

        for fill in &fills {
            let instrument = self.resolve_report_instrument(fill.symbol).await?;
            let report = parse_fill_report(fill, account_id, &instrument, ts_init)
                .with_context(|| format!("Failed to parse AX fill {}", fill.trade_id))?;
            reports.push(report);
        }

        Ok(reports)
    }

View on GitHub (pinned to 18893faf8b)