nautechsystems/nautilus_trader · error
Lighter fill reconciliation repeated cursor `{next}`
Error message
Lighter fill reconciliation repeated cursor `{next}` What it means
During paginated fill reconciliation, each returned next_cursor is inserted into a `seen_cursors` set. If the exchange returns a cursor that was already served, pagination would loop forever, so the adapter fails fast with this error. It detects a server-side cursor cycle.
Source
Thrown at crates/adapters/lighter/src/execution.rs:5344
.filter_map(|trade| u64::try_from(trade.timestamp).ok())
.map(|timestamp_ms| UnixNanos::from(timestamp_ms.saturating_mul(1_000_000)))
.min();
if let Some(page_oldest) = page_oldest {
oldest_served = Some(oldest_served.map_or(page_oldest, |ts| ts.min(page_oldest)));
}
let reached_start_boundary = cmd
.start
.is_some_and(|start| page_oldest.is_some_and(|oldest| oldest < start));
if reached_start_boundary {
break;
}
match response.next_cursor {
Some(next) if !next.is_empty() => {
anyhow::ensure!(
seen_cursors.insert(next.clone()),
"Lighter fill reconciliation repeated cursor `{next}`",
);
cursor = Some(next);
}
_ => {
// The venue retains a bounded number of recent trades per account,
// so an exhausted cursor ends the retained history rather than the
// account's. Only a trade older than `start` proves the requested
// window was served in full; an account-wide sweep that served
// nothing has no history to retain.
if let (Some(start), Some(oldest)) = (cmd.start, oldest_served) {
covers_window = false;
log::warn!(
"Lighter fill reports do not cover {} to {}: trade pagination exhausted before the requested start; the venue `export` endpoint serves full history",
unix_nanos_to_iso8601(start),
unix_nanos_to_iso8601(oldest),View on GitHub (pinned to 18893faf8b)
Solutions
- Retry the reconciliation after a short delay; cursor cycles are usually transient.
- Check Lighter status/announcements for known API pagination issues.
- Narrow the reconciliation window to reduce reliance on deep pagination.
- If persistent, capture the repeated cursor value and report it to Lighter support.
Defensive patterns
Strategy: retry
Try / catch
match res {
Err(e) if e.to_string().contains("repeated cursor") => {
tokio::time::sleep(BACKOFF).await;
retry_reconciliation();
}
other => other,
} Prevention
- Treat repeated-cursor aborts as transient and retry with backoff
- Monitor Lighter API status for pagination incidents
- Alert on repeated occurrences — persistent cycles need exchange support
When it happens
Trigger: Lighter trades endpoint returning a repeated next_cursor during paginated fill reconciliation — typically an exchange-side anomaly or API bug, not a client config problem.
Common situations: Lighter API incidents where cursor pagination degenerates into a cycle; transient backend issues during heavy load.
Related errors
- Lighter fill reconciliation exceeded {MAX_RECONCILIATION_PAG
- Lighter active-market seed repeated cursor `{next}`
- Failed to fetch fills: {e}
- no Lighter market_index for fill instrument {instrument_id}
- Lighter active-market seed exceeded {MAX_RECONCILIATION_PAGE
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/df9c5ab58ce2d00e.
Report an issue: GitHub.