nautechsystems/nautilus_trader · error · anyhow::Error

AX fills total_count must be non-negative, was {total_count}

Error message

AX fills total_count must be non-negative, was {total_count}

What it means

While paginating GET /fills in request_fill_reports, the Architect HTTP client validates the server-supplied total_count on every page and requires it to be >= 0. A negative total_count means the server is reporting a corrupt or sentinel counter, so the adapter aborts the whole fills request instead of reconciling against garbage. This is a fail-fast contract guard, not a client-side data error.

Source

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

            anyhow::ensure!(
                page_len <= PAGE_SIZE as usize,
                "AX fills page length {page_len} exceeds requested limit {PAGE_SIZE}"
            );

            if let Some(limit) = response.limit {
                anyhow::ensure!(
                    (0..=PAGE_SIZE).contains(&limit),
                    "AX fills applied limit must be between 0 and {PAGE_SIZE}, was {limit}"
                );
                anyhow::ensure!(
                    page_len <= limit as usize,
                    "AX fills page length {page_len} exceeds applied limit {limit}"
                );
            }

            if let Some(total_count) = response.total_count {
                anyhow::ensure!(
                    total_count >= 0,
                    "AX fills total_count must be non-negative, was {total_count}"
                );

                if let Some(expected) = expected_total {
                    anyhow::ensure!(
                        total_count == expected,
                        "AX fills total_count changed during pagination: expected {expected}, was {total_count}"
                    );
                } else {
                    expected_total = Some(total_count);
                }
            }

            for fill in response.fills {
                anyhow::ensure!(
                    seen_trade_ids.insert(fill.trade_id.clone()),
                    "AX fills pagination returned duplicate trade ID {}",

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Log or curl the raw /fills response body for the failing cursor and confirm the total_count field is actually negative
  2. Check the AX API changelog/docs for whether total_count can be a sentinel (e.g. -1 for unknown) in the API version you target
  3. If -1 is a legal 'unknown' marker, patch the response deserialization upstream of this guard (map negative to None) via a PR rather than weakening the ensure!
  4. Retry the request once to rule out transient payload corruption from proxies

Example fix

// before (stub /fills response)
{"fills": [...], "next_cursor": null, "total_count": -1}
// after
{"fills": [...], "next_cursor": null, "total_count": 42}
Defensive patterns

Strategy: retry

Try / catch

match client.request_fill_reports(account_id, start, end).await {
    Ok(reports) => { /* reconcile */ }
    Err(e) if e.to_string().contains("total_count must be non-negative") => {
        log::error!("AX returned negative total_count; retrying once: {e}");
        // single retry with backoff; escalate if it repeats
        tokio::time::sleep(Duration::from_secs(2)).await;
        client.request_fill_reports(account_id, start, end).await?;
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: A /fills page (GET with cursor, limit=100, sort_ts=desc, 7-day bounded window) returns a JSON total_count of -1 or any negative value. Typical sources: a server-side 'unknown count' sentinel, an unsigned/signed encoding bug in the AX API, a mock/test server returning defaulted i64 values, or a proxy mangling the response body.

Common situations: Pointing the client at a stub/test harness that does not implement total_count; an AX API version bump that changed total_count semantics; gateway or recording middleware that re-serializes the payload incorrectly.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/adc8aa59e5b324de. Report an issue: GitHub.