{"record":{"id":"f634919fd759e50b","repo":"nautechsystems/nautilus_trader","slug":"fill-report-start-time-must-not-exceed-end-time","errorCode":null,"errorMessage":"fill report start time must not exceed end time","messagePattern":"fill report start time must not exceed end time","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/futures/execution.rs","lineNumber":1994,"sourceCode":"    ) -> anyhow::Result<Vec<FillReport>> {\n        let Some(instrument_id) = cmd.instrument_id else {\n            log::warn!(\"generate_fill_reports requires instrument_id for Binance Futures\");\n            return Ok(Vec::new());\n        };\n\n        let symbol = format_binance_symbol(&instrument_id);\n        let mut trades = Vec::new();\n        let mut seen_trade_ids = AHashSet::new();\n        let requested_end_time = cmd\n            .end\n            .map(|end| end.as_i64() / NANOSECONDS_IN_MILLISECOND as i64);\n\n        if let Some(start) = cmd.start {\n            let query_start_time = start.as_i64() / NANOSECONDS_IN_MILLISECOND as i64;\n            let query_end_time = requested_end_time.unwrap_or_else(|| {\n                self.clock.get_time_ns().as_i64() / NANOSECONDS_IN_MILLISECOND as i64\n            });\n            anyhow::ensure!(\n                query_start_time <= query_end_time,\n                \"fill report start time must not exceed end time\"\n            );\n            let mut window_start = query_start_time;\n\n            loop {\n                let window_end = window_start\n                    .saturating_add(USER_TRADES_MAX_INTERVAL_MS)\n                    .min(query_end_time);\n                let mut from_id = None;\n\n                loop {\n                    let mut builder = BinanceUserTradesParamsBuilder::default();\n                    builder.symbol(symbol.clone());\n                    builder.limit(USER_TRADES_PAGE_LIMIT);\n\n                    if let Some(cursor) = from_id {\n                        builder.from_id(cursor);","sourceCodeStart":1976,"sourceCodeEnd":2012,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/binance/src/futures/execution.rs#L1976-L2012","documentation":"generate_fill_reports validates the requested window before querying /fapi/v1/userTrades: the start time (ms) must not exceed the effective end time, where end defaults to the current clock time when cmd.end is None. An inverted range would paginate meaningless windows, so the client fails fast. This mirrors guards common to all historical-report generators that take start/end pairs.","triggerScenarios":"Issuing GenerateFillReports with start > end, or with a future start and end omitted (since end then defaults to now, any start in the future trips the guard); also start/end swapped in caller code.","commonSituations":"Clock skew between the caller and the client host; datetime conversions mixing timezones so start lands after end; reconciliation code passing a session window the wrong way round.","solutions":["Order the arguments so start <= end and validate before issuing the report","When end is None, ensure start is in the past relative to the host clock","Normalize/clamp the range (e.g. swap if inverted) in the code that builds the report command"],"exampleFix":"// before\nlet report = client\n    .generate_fill_reports(GenerateFillReports::new(account_id, Some(future_start), None))\n    .await?;\n\n// after\nlet report = client\n    .generate_fill_reports(GenerateFillReports::new(account_id, Some(past_start), Some(later_end)))\n    .await?;","handlingStrategy":"validation","validationCode":"let start_ms = cmd.start.map(|t| t.as_i64() / 1_000_000);\nlet end_ms = cmd.end.map(|t| t.as_i64() / 1_000_000)\n    .unwrap_or_else(|| clock.get_time_ns().as_i64() / 1_000_000);\nif let Some(s) = start_ms {\n    anyhow::ensure!(s <= end_ms, \"inverted fill-report window\");\n}","typeGuard":"fn valid_report_window(start_ms: i64, end_ms: i64) -> bool {\n    start_ms <= end_ms\n}","tryCatchPattern":null,"preventionTips":["Clamp report ranges server-side: start = min(start, end), both <= now","Use a single clock/timezone source when building report windows","Log both timestamps when dispatching report commands to diagnose skew"],"tags":["binance-futures","fill-reports","time-range","user-trades","rust"],"backgroundTag":"invalid-time-range","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}