{"record":{"id":"ff1b36cf092f1d43","repo":"nautechsystems/nautilus_trader","slug":"ax-fills-total-count-changed-during-pagination-ex","errorCode":null,"errorMessage":"AX fills total_count changed during pagination: expected {expected}, was {total_count}","messagePattern":"AX fills total_count changed during pagination: expected (.+?), was (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/http/client.rs","lineNumber":2248,"sourceCode":"            if let Some(limit) = response.limit {\n                anyhow::ensure!(\n                    (0..=PAGE_SIZE).contains(&limit),\n                    \"AX fills applied limit must be between 0 and {PAGE_SIZE}, was {limit}\"\n                );\n                anyhow::ensure!(\n                    page_len <= limit as usize,\n                    \"AX fills page length {page_len} exceeds applied limit {limit}\"\n                );\n            }\n\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 {","sourceCodeStart":2230,"sourceCodeEnd":2266,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/architect_ax/src/http/client.rs#L2230-L2266","documentation":"During multi-page AX fills pagination, the first page's total_count is captured and every later page must report the identical value. If the total changes mid-pagination, the result set mutated while being read (fills added or removed), so the client aborts rather than return an inconsistent snapshot.","triggerScenarios":"Paginating fills across two or more requests where a later page's `total_count` differs from the value captured on the first page — e.g. new fills arrived or old ones were amended/deleted between page fetches.","commonSituations":"Fetching fills over a live/unbounded time range while trading continues; a background reconciliation job mutates fills; querying without pinning an end timestamp.","solutions":["Re-run the pagination with an end time / snapshot pinned to a moment in the past so the dataset is immutable during the fetch.","Retry the full pagination; transient concurrent writes may have resolved.","Narrow the query window to reduce the chance of concurrent fills landing inside it.","If totals legitimately change constantly, use a streaming/incremental fills endpoint instead of snapshot pagination."],"exampleFix":"// before: open-ended query, totals drift while paging\nlet params = FillsParams { start: Some(hour_ago), ..Default::default() };\n// after: bound both ends so the snapshot is stable\nlet params = FillsParams { start: Some(hour_ago), end: Some(now), ..Default::default() };","handlingStrategy":"retry","validationCode":"// use a closed time window so the dataset cannot grow during pagination\nlet params = FillsParams { start: Some(start), end: Some(end), ..Default::default() };","typeGuard":null,"tryCatchPattern":"match client.paginate_fills(params).await {\n    Ok(fills) => apply(fills),\n    Err(e) if e.to_string().contains(\"total_count changed during pagination\") => {\n        info!(\"fills mutated mid-read; retrying snapshot\");\n        client.paginate_fills(params).await\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always pin an end timestamp on fills queries over live data.","Pause or sequence fills syncs relative to reconciliation jobs.","Keep query windows short to reduce mutation exposure."],"tags":["rust","pagination","consistency","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"}