nautechsystems/nautilus_trader · error · anyhow::Error
fill report start time must not exceed end time
Error message
fill report start time must not exceed end time
What it means
GenerateFillReports converts the command's start/end (nanoseconds) to milliseconds and validates the window: if both are provided, start must not exceed end. This guards the Binance myTrades queries so an inverted window is rejected before any request is made.
Source
Thrown at crates/adapters/binance/src/spot/execution.rs:1187
) -> anyhow::Result<Vec<FillReport>> {
let Some(instrument_id) = cmd.instrument_id else {
log::warn!("generate_fill_reports requires instrument_id for Binance Spot");
return Ok(Vec::new());
};
// Convert ClientOrderId to VenueOrderId if provided (API naming quirk)
let venue_order_id = cmd
.venue_order_id
.as_ref()
.map(|id| VenueOrderId::new(id.inner()));
let requested_start_time = cmd
.start
.map(|start| start.as_i64() / NANOSECONDS_IN_MILLISECOND as i64);
let requested_end_time = cmd
.end
.map(|end| end.as_i64() / NANOSECONDS_IN_MILLISECOND as i64);
if let (Some(start), Some(end)) = (requested_start_time, requested_end_time) {
anyhow::ensure!(
start <= end,
"fill report start time must not exceed end time"
);
}
let mut reports = Vec::new();
let mut seen_trade_ids = AHashSet::new();
if venue_order_id.is_some() {
let mut from_id = 0;
loop {
let page = self
.http_client
.request_fill_reports_with_cursor(
self.core.account_id,
instrument_id,
venue_order_id,View on GitHub (pinned to a4b06ed870)
Solutions
- Order the window: pass the earlier time as start and the later time as end
- Omit end so it defaults to the current clock time
- Double-check timestamp units (Nautilus uses unix nanoseconds; the adapter converts to Binance ms)
Example fix
// before
let cmd = GenerateFillReportsBuilder::default()
.start(end_ts) // swapped
.end(start_ts)
.build()?;
// after
let cmd = GenerateFillReportsBuilder::default()
.start(start_ts)
.end(end_ts)
.build()?; Defensive patterns
Strategy: validation
Validate before calling
fn normalize_window(start_ms: i64, end_ms: i64) -> anyhow::Result<(i64, i64)> {
anyhow::ensure!(start_ms <= end_ms, "start {start_ms}ms after end {end_ms}ms");
Ok((start_ms, end_ms))
} Prevention
- Build report windows from a single (start, duration) pair instead of two independent timestamps
- Assert timestamp units at the boundary (ns in Nautilus, ms at Binance)
- For scripted scans, derive end from the clock rather than a hardcoded value
When it happens
Trigger: Requesting fill reports (mass status or a direct GenerateFillReports command) with a start timestamp later than the end timestamp — e.g. swapped arguments, or a start in the future relative to a fixed end.
Common situations: Manually built report commands with swapped start/end; timezone or unit confusion (passing seconds where ms are expected then converting); scripted backfills with templated dates.
Related errors
- Spot ticker requires a BINANCE instrument
- Binance Spot L1_MBP supports depth 1 only
- Binance Spot supports L1_MBP and L2_MBP order book subscript
- historical BinanceBar requests require EXTERNAL aggregation
- historical BinanceBar requests require LAST price type
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/5dfcff6d9b8784f4.
Report an issue: GitHub.