nautechsystems/nautilus_trader · error
Binance Spot account-trades pagination made no progress
Error message
Binance Spot account-trades pagination made no progress
What it means
When paginating account trades by venue order id, the loop advances fromId = max_trade_id + 1 after each full ACCOUNT_TRADES_PAGE_LIMIT page. If the next cursor is not greater than the current from_id the loop would spin forever, so the adapter bails with this no-progress guard (spot/execution.rs:1238).
Source
Thrown at crates/adapters/binance/src/spot/execution.rs:1238
page.iter().any(|report| report_time_ms(report) > end_time)
});
reports.extend(page.into_iter().filter(|report| {
requested_start_time
.is_none_or(|start_time| report_time_ms(report) >= start_time)
&& requested_end_time
.is_none_or(|end_time| report_time_ms(report) <= end_time)
&& seen_trade_ids.insert(report.trade_id)
}));
if page_len < ACCOUNT_TRADES_PAGE_LIMIT as usize || passed_end {
break;
}
let next_from_id = max_trade_id
.checked_add(1)
.context("Binance Spot trade ID overflow during pagination")?;
anyhow::ensure!(
next_from_id > from_id,
"Binance Spot account-trades pagination made no progress"
);
from_id = next_from_id;
}
} else if let Some(query_start_time) = requested_start_time {
let query_end_time = requested_end_time.unwrap_or_else(|| {
self.clock.get_time_ns().as_i64() / NANOSECONDS_IN_MILLISECOND as i64
});
anyhow::ensure!(
query_start_time <= query_end_time,
"fill report start time must not exceed end time"
);
let mut window_start = query_start_time;
loop {
let window_end = window_start
.saturating_add(ACCOUNT_TRADES_MAX_INTERVAL_MS)View on GitHub (pinned to a4b06ed870)
Solutions
- Re-run the fill report with a narrower time window or after new trades exist
- Avoid issuing overlapping fill-report scans concurrently; keep a watermark of the last seen trade time
- If it persists, capture the raw myTrades response for the fromId range and report it to the NautilusTrader maintainers
Defensive patterns
Strategy: retry
Validate before calling
// keep a watermark so successive fill-report scans never rescan fully-seen pages let start = last_fill_scan_ts.map(|t| t + 1.nanos()); // advance strictly
Try / catch
match generate_fill_reports(cmd).await {
Err(e) if e.to_string().contains("pagination made no progress") => {
// narrow the window and retry once; if it repeats, capture raw pages and report upstream
}
other => other?,
} Prevention
- Persist the last processed trade id/time and always resume from that watermark
- Prefer venue_order_id-scoped fill queries when reconciling a single order
- Avoid running two overlapping mass-status generations over the same window
When it happens
Trigger: Binance keeps returning full pages while the local filters (seen_trade_ids dedupe and the requested time window) discard every row, so max_trade_id never advances past the cursor — anomalous API behavior or a pathological window/dedupe interaction.
Common situations: Repeatedly running fill-report scans over the same window so every trade is already deduped; venue-side behavior changes returning unfiltered data outside the requested window; concurrent overlapping report generations.
Related errors
- Binance user-trades pagination made no progress
- Binance Spot trade limit must not exceed 1000
- fill report start time must not exceed end time
- Symbol '{}' is not trading (status: {})
- Invalid tickSize of 0
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/ec62e480f188d8f8.
Report an issue: GitHub.