{"record":{"id":"69d3a09328052056","repo":"nautechsystems/nautilus_trader","slug":"ax-fills-pagination-returned-duplicate-trade-id","errorCode":null,"errorMessage":"AX fills pagination returned duplicate trade ID {}","messagePattern":"AX fills pagination returned duplicate trade ID (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/http/client.rs","lineNumber":2258,"sourceCode":"\n            if let Some(total_count) = response.total_count {\n                anyhow::ensure!(\n                    total_count >= 0,\n                    \"AX fills total_count must be non-negative, was {total_count}\"\n                );\n\n                if let Some(expected) = expected_total {\n                    anyhow::ensure!(\n                        total_count == expected,\n                        \"AX fills total_count changed during pagination: expected {expected}, was {total_count}\"\n                    );\n                } else {\n                    expected_total = Some(total_count);\n                }\n            }\n\n            for fill in response.fills {\n                anyhow::ensure!(\n                    seen_trade_ids.insert(fill.trade_id.clone()),\n                    \"AX fills pagination returned duplicate trade ID {}\",\n                    fill.trade_id\n                );\n                fills.push(fill);\n            }\n\n            if let Some(total_count) = expected_total {\n                anyhow::ensure!(\n                    fills.len() as i64 <= total_count,\n                    \"AX fills pagination returned more unique rows ({}) than total_count {total_count}\",\n                    fills.len()\n                );\n            }\n\n            match response.next_cursor {\n                Some(next_cursor) => {\n                    anyhow::ensure!(","sourceCodeStart":2240,"sourceCodeEnd":2276,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/architect_ax/src/http/client.rs#L2240-L2276","documentation":"The paginator tracks trade IDs it has already seen across all pages via a HashSet; if the same trade_id appears twice, the server is re-serving rows (bad cursor advancement or overlap) and the client aborts to prevent duplicated fills in the result.","triggerScenarios":"Any fills page iteration where a response contains a fill whose trade_id was already collected from an earlier page — duplicate delivery caused by server-side cursor overlap or a cursor that advanced incorrectly.","commonSituations":"Server cursor semantics changed after a backend deploy; a load balancer routes page requests to different replicas with divergent snapshots; retry logic re-delivers the tail of the previous page.","solutions":["Retry the whole pagination from scratch; a transient replica mismatch often resolves.","Check whether a proxy/LB is serving inconsistent replicas and pin to a single endpoint.","Compare the raw JSON of the previous and current pages to confirm the overlapping trade IDs and report to the AX backend team.","Upgrade the client in case cursor-advance semantics changed server-side."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match client.paginate_fills(params).await {\n    Ok(fills) => apply(fills),\n    Err(e) if e.to_string().contains(\"duplicate trade ID\") => {\n        warn!(\"AX served overlapping pages; restarting pagination\");\n        client.paginate_fills(params).await\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Deduplicate by trade_id downstream as an extra safety net.","Pin fills reads to a single endpoint/replica where possible.","Watch for backend deploys that change cursor semantics."],"tags":["rust","pagination","deduplication","http-client"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}