nautechsystems/nautilus_trader · error · anyhow::Error

AX open-orders page exceeds total_count: next offset {next_o

Error message

AX open-orders page exceeds total_count: next offset {next_offset}, total {total_count}

What it means

After each page, the client computes next_offset = offset + page_len and asserts it never exceeds total_count. A page that pushes the offset past the advertised total means the server returned more rows than it said exist, breaking the pagination contract and risking phantom/duplicated orders.

Source

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

            let total_count = *expected_total.get_or_insert(response.total_count);
            anyhow::ensure!(
                response.total_count == total_count,
                "AX open-orders total_count changed during pagination: expected {total_count}, was {}",
                response.total_count
            );

            let page_len = i64::try_from(response.orders.len())
                .context("AX open-orders page length exceeds i64")?;
            anyhow::ensure!(
                page_len <= i64::from(response.limit),
                "AX open-orders page length {page_len} exceeds applied limit {}",
                response.limit
            );
            let next_offset = offset
                .checked_add(page_len)
                .context("AX open-orders offset overflow")?;
            anyhow::ensure!(
                next_offset <= total_count,
                "AX open-orders page exceeds total_count: next offset {next_offset}, total {total_count}"
            );

            if total_count == 0 {
                anyhow::ensure!(
                    response.orders.is_empty(),
                    "AX open-orders returned rows with total_count zero"
                );
                break;
            }

            anyhow::ensure!(
                !response.orders.is_empty(),
                "AX open-orders returned an empty page before offset {offset} reached total {total_count}"
            );

            for order in response.orders {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Restart pagination from offset 0 to get a fresh consistent total
  2. Verify request parameters (offset, limit) are sent as intended
  3. Report the malformed pagination response to AX/adapter maintainers
  4. Snapshot orders with a single large page if feasible to avoid multi-page arithmetic
Defensive patterns

Strategy: retry

Validate before calling

// Validate before consuming: accumulated rows must never exceed the advertised total
assert!(fetched_so_far + page.orders.len() as i64 <= page.total_count,
    "pagination would exceed total_count {}", page.total_count);

Try / catch

match result {
    Err(e) if e.to_string().contains("page exceeds total_count") => restart_pagination_from_zero(),
    Err(e) => return Err(e),
    Ok(orders) => use(orders),
}

Prevention

When it happens

Trigger: A page's row count, accumulated from offset 0, exceeds the total_count the server reported, e.g. server returning overlapping pages or an inconsistent total.

Common situations: Venue-side pagination bugs; total_count shrinking while pages still return old rows; API version changes altering page semantics.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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