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

  1. Order the window: pass the earlier time as start and the later time as end
  2. Omit end so it defaults to the current clock time
  3. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/5dfcff6d9b8784f4. Report an issue: GitHub.