{"record":{"id":"d4e2f6fe4dcc25b0","repo":"nautechsystems/nautilus_trader","slug":"ax-fills-pagination-repeated-cursor-next-cursor","errorCode":null,"errorMessage":"AX fills pagination repeated cursor {next_cursor:?}","messagePattern":"AX fills pagination repeated cursor (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/http/client.rs","lineNumber":2284,"sourceCode":"            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!(\n                        !next_cursor.is_empty(),\n                        \"AX fills returned an empty next_cursor\"\n                    );\n                    anyhow::ensure!(\n                        page_len > 0,\n                        \"AX fills returned an empty page with a next_cursor\"\n                    );\n                    anyhow::ensure!(\n                        seen_cursors.insert(next_cursor.clone()),\n                        \"AX fills pagination repeated cursor {next_cursor:?}\"\n                    );\n                    params.cursor = Some(next_cursor);\n                }\n                None => break,\n            }\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 {} unique rows, expected {total_count}\",\n                fills.len()\n            );\n        }\n\n        let ts_init = self.generate_ts_init();","sourceCodeStart":2266,"sourceCodeEnd":2302,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/architect_ax/src/http/client.rs#L2266-L2302","documentation":"The paginator records every next_cursor it receives; if the server ever returns a cursor it already returned, pagination would cycle forever over the same rows. The client detects the repeat and aborts, both preventing an infinite loop and surfacing the server-side cursor bug.","triggerScenarios":"During fills pagination, a later page's next_cursor equals a cursor already used in an earlier request — the server failed to advance its cursor.","commonSituations":"Cursor computed from an unstable sort key (e.g. non-unique timestamp) causing the server to stall at the same position; backend deploy changed cursor encoding; load-balanced replicas returning divergent cursors.","solutions":["Retry the pagination once; transient stalls may not recur.","Check that fills have a unique, stable ordering key; report non-advancing cursors to the AX backend team with the repeated cursor value logged.","Bound the loop client-side anyway (max pages) as a defensive habit, even though this check aborts cycles.","Pin requests to one replica/endpoint to rule out divergent cursor state."],"exampleFix":"// before: unbounded loop trusting the server to terminate\nloop { let page = client.fills(¶ms).await?; /* ... */ }\n// after: bound the iterations defensively\nfor _ in 0..MAX_PAGES { let page = client.fills(¶ms).await?; /* ... */ }","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(\"repeated cursor\") => {\n        error!(\"AX cursor stalled; aborting this sync cycle and alerting\");\n        Err(e)\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Bound pagination loops externally even though the client detects cycles.","Ensure fills have stable unique ordering server-side.","Pin reads to one replica to avoid divergent cursor state."],"tags":["rust","pagination","cursor","infinite-loop"],"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"}