nautechsystems/nautilus_trader · error · anyhow::Error
AX open-orders pagination returned duplicate order ID {}
Error message
AX open-orders pagination returned duplicate order ID {} What it means
The open-orders pagination collects all order IDs in a seen-set and aborts if the same oid appears twice across pages. Duplicates would corrupt the caller's view of open orders (double-counted positions/sizes), so the client treats repetition as a contract violation.
Source
Thrown at crates/adapters/architect_ax/src/http/client.rs:2049
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);
}
if next_offset == total_count {
break;
}
offset = next_offset;
}
anyhow::ensure!(
i64::try_from(orders.len()).context("AX open-orders result length exceeds i64")?
== expected_total.unwrap_or_default(),
"AX open-orders pagination did not return the advertised number of unique orders"View on GitHub (pinned to 18893faf8b)
Solutions
- Restart pagination from offset 0 and complete it quickly
- Request a stable sort parameter if the API supports it, so rows don't shift between pages
- Increase page size to finish in one page, eliminating offset-shift risk
- Report overlapping-page behavior to AX/adapter maintainers with the raw responses
Defensive patterns
Strategy: retry
Validate before calling
let mut seen = std::collections::HashSet::new();
for o in &all_orders {
if !seen.insert(o.oid.clone()) {
return Err(anyhow!("duplicate order {} across pages", o.oid));
}
} Try / catch
match result {
Err(e) if e.to_string().contains("duplicate order ID") => restart_pagination_with_stable_sort(),
Err(e) => return Err(e),
Ok(orders) => use(orders),
} Prevention
- Request a stable sort from the API if supported so rows don't shift between pages
- Increase page size to fetch everything in one page
- Avoid order inserts from other processes on the same account during pagination
When it happens
Trigger: Server returns overlapping pages — e.g. rows inserted before the current offset during pagination, or unstable sort order shifting rows between pages.
Common situations: New orders inserted server-side mid-pagination shifting offsets; venue returning unsorted data that the adapter assumes is stable; API regression in page slicing.
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 rows with total_count zero
- AX open-orders returned an empty page before offset {offset}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0e95f8be1ce6d7e3.
Report an issue: GitHub.