nautechsystems/nautilus_trader · error · anyhow::Error
AX open-orders returned rows with total_count zero
Error message
AX open-orders returned rows with total_count zero
What it means
When the venue advertises total_count of 0, the client requires the page to contain zero rows. Receiving rows alongside total_count=0 means the server's total is wrong, so the client refuses the response instead of trusting inconsistent metadata.
Source
Thrown at crates/adapters/architect_ax/src/http/client.rs:2036
);
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 {
anyhow::ensure!(
seen_order_ids.insert(order.oid.clone()),
"AX open-orders pagination returned duplicate order ID {}",
order.oid
);
orders.push(order);View on GitHub (pinned to 18893faf8b)
Solutions
- Retry the request after a short delay so server-side counts catch up
- Confirm the query filters sent match the API's documented semantics
- Capture the raw response and report the inconsistent total to the venue
- Trust rows over totals defensively only if you control the adapter fork
Defensive patterns
Strategy: retry
Validate before calling
if page.total_count == 0 && !page.orders.is_empty() {
// inconsistent; wait and refetch
std::thread::sleep(Duration::from_millis(200));
return fetch_open_orders();
} Type guard
fn is_consistent(total: i64, rows: usize) -> bool {
total > 0 || rows == 0
} Try / catch
match result {
Err(e) if e.to_string().contains("rows with total_count zero") => {
tokio::time::sleep(Duration::from_millis(250)).await;
retry_fetch()
}
other => other,
} Prevention
- Add a short backoff-and-retry around open-order polls
- Ensure query filters match the API's documented counting semantics
- Report persistent zero-total-with-rows responses to AX support
When it happens
Trigger: The first open-orders page returns orders but reports total_count=0 — the server's count field disagrees with its payload.
Common situations: Newly placed orders not yet reflected in the venue's count; AX API bug or caching layer returning stale totals; adapter sending filters the server counts differently than it filters rows.
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
- AX open-orders total_count changed during pagination: expect
- AX open-orders page length {page_len} exceeds applied limit
- AX open-orders page exceeds total_count: next offset {next_o
- AX open-orders returned an empty page before offset {offset}
- AX open-orders pagination returned duplicate order ID {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/2822aed28ee27999.
Report an issue: GitHub.