{"record":{"id":"9687430e00451492","repo":"nautechsystems/nautilus_trader","slug":"ax-open-orders-returned-an-empty-page-before-offse","errorCode":null,"errorMessage":"AX open-orders returned an empty page before offset {offset} reached total {total_count}","messagePattern":"AX open-orders returned an empty page before offset (.+?) reached total (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/http/client.rs","lineNumber":2043,"sourceCode":"                response.limit\n            );\n            let next_offset = offset\n                .checked_add(page_len)\n                .context(\"AX open-orders offset overflow\")?;\n            anyhow::ensure!(\n                next_offset <= total_count,\n                \"AX open-orders page exceeds total_count: next offset {next_offset}, total {total_count}\"\n            );\n\n            if total_count == 0 {\n                anyhow::ensure!(\n                    response.orders.is_empty(),\n                    \"AX open-orders returned rows with total_count zero\"\n                );\n                break;\n            }\n\n            anyhow::ensure!(\n                !response.orders.is_empty(),\n                \"AX open-orders returned an empty page before offset {offset} reached total {total_count}\"\n            );\n\n            for order in response.orders {\n                anyhow::ensure!(\n                    seen_order_ids.insert(order.oid.clone()),\n                    \"AX open-orders pagination returned duplicate order ID {}\",\n                    order.oid\n                );\n                orders.push(order);\n            }\n\n            if next_offset == total_count {\n                break;\n            }\n\n            offset = next_offset;","sourceCodeStart":2025,"sourceCodeEnd":2061,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/architect_ax/src/http/client.rs#L2025-L2061","documentation":"During offset pagination, a mid-stream empty page before reaching total_count means rows are missing: the server advertised more orders than it will ever return at the current offsets. The client fails fast rather than silently returning fewer orders than the venue promised.","triggerScenarios":"Server returns an empty orders array while offset < total_count, e.g. rows were removed server-side after the total was computed, or a page boundary bug skips rows.","commonSituations":"Orders canceled during pagination; venue soft-deleting rows without adjusting totals; API pagination endpoint regression.","solutions":["Retry the full pagination from offset 0","Re-check whether the orders were legitimately canceled mid-poll (expected churn, not a bug)","Verify the adapter's offset/limit parameters against current AX API docs","Increase page size to reduce the number of pages and the window for churn"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if offset < total_count && page.orders.is_empty() {\n    return Err(anyhow!(\"empty page at offset {offset}, total {total_count}\"));\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"empty page before offset\") => restart_pagination(),\n    Err(e) => return Err(e),\n    Ok(orders) => use(orders),\n}","preventionTips":["Expect mid-poll cancellations on active accounts and retry the full loop","Increase page size to reduce page count and churn exposure","Verify offset/limit parameters against current AX API docs"],"tags":["pagination","http","empty-page"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}