{"record":{"id":"25c0c93a1dd46fe2","repo":"nautechsystems/nautilus_trader","slug":"invalid-time-range-start-s-end-e-25c0c9","errorCode":null,"errorMessage":"Invalid time range: start={s:?} end={e:?}","messagePattern":"Invalid time range: start=(.+?) end=(.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/http/client.rs","lineNumber":3185,"sourceCode":"        start: Option<Timestamp>,\n        end: Option<Timestamp>,\n        limit: Option<u32>,\n    ) -> anyhow::Result<Vec<TradeTick>> {\n        const OKX_TRADES_MAX_LIMIT: u32 = 100;\n        const MAX_PAGES: usize = 500;\n        const MAX_CONSECUTIVE_EMPTY: usize = 3;\n\n        #[derive(Clone, Copy, Debug, PartialEq, Eq)]\n        enum Mode {\n            Latest,\n            Backward,\n            Range,\n        }\n\n        let limit = if limit == Some(0) { None } else { limit };\n\n        if let (Some(s), Some(e)) = (start, end) {\n            anyhow::ensure!(s < e, \"Invalid time range: start={s:?} end={e:?}\");\n        }\n\n        let now = self.inner.clock.get_time_ns().to_datetime_utc();\n\n        if let Some(s) = start\n            && s > now\n        {\n            return Ok(Vec::new());\n        }\n\n        let end = if let Some(e) = end\n            && e > now\n        {\n            Some(now)\n        } else {\n            end\n        };\n","sourceCodeStart":3167,"sourceCodeEnd":3203,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/http/client.rs#L3167-L3203","documentation":"A time-range validation using anyhow::ensure!: when both start and end are provided for a historical data request, start must be strictly earlier than end, otherwise this error names both values. It is a client-side guard that prevents pointless doomed requests to OKX.","triggerScenarios":"Calling a history/instruments request with start >= end (equal or inverted timestamps), e.g. passing the same datetime for both bounds or swapping them.","commonSituations":"Computing start/end from off-by-one window arithmetic, unit tests with identical timestamps, timezone conversions shifting end before start, or user-supplied query parameters passed through unvalidated.","solutions":["Validate the range in your caller: assert start < end before invoking the request.","Swap the values if your data source returns them in the opposite order.","When start == end is meaningful (single point), omit one bound or widen the window by 1 unit.","Review timezone handling so both bounds use the same tz before comparison."],"exampleFix":"// before\nlet (start, end) = (end_ts, start_ts); // inverted by mistake\nclient.request_trades(instrument_id, Some(start), Some(end), None).await?;\n// after\nassert!(start_ts < end_ts, \"start must precede end\");\nclient.request_trades(instrument_id, Some(start_ts), Some(end_ts), None).await?;","handlingStrategy":"validation","validationCode":"if let (Some(s), Some(e)) = (start, end) {\n    assert!(s < e, \"start must be before end: {s:?} vs {e:?}\");\n}","typeGuard":null,"tryCatchPattern":"match client.request_trades(instrument_id, start, end, None).await {\n    Err(e) if e.to_string().contains(\"Invalid time range\") => { /* fix bounds and retry */ }\n    other => other?,\n}","preventionTips":["Compute start/end in a single timezone and clamp end to now.","Reject empty/inverted windows at your API boundary before calling the adapter.","Add a property-style test that start < end for all generated windows."],"tags":["okx","validation","time-range","parameters"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}