nautechsystems/nautilus_trader · error · anyhow::Error
Invalid time range: start={s:?} end={e:?}
Error message
Invalid time range: start={s:?} end={e:?} What it means
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.
Source
Thrown at crates/adapters/okx/src/http/client.rs:3185
start: Option<Timestamp>,
end: Option<Timestamp>,
limit: Option<u32>,
) -> anyhow::Result<Vec<TradeTick>> {
const OKX_TRADES_MAX_LIMIT: u32 = 100;
const MAX_PAGES: usize = 500;
const MAX_CONSECUTIVE_EMPTY: usize = 3;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Mode {
Latest,
Backward,
Range,
}
let limit = if limit == Some(0) { None } else { limit };
if let (Some(s), Some(e)) = (start, end) {
anyhow::ensure!(s < e, "Invalid time range: start={s:?} end={e:?}");
}
let now = self.inner.clock.get_time_ns().to_datetime_utc();
if let Some(s) = start
&& s > now
{
return Ok(Vec::new());
}
let end = if let Some(e) = end
&& e > now
{
Some(now)
} else {
end
};
View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before let (start, end) = (end_ts, start_ts); // inverted by mistake client.request_trades(instrument_id, Some(start), Some(end), None).await?; // after assert!(start_ts < end_ts, "start must precede end"); client.request_trades(instrument_id, Some(start_ts), Some(end_ts), None).await?;
Defensive patterns
Strategy: validation
Validate before calling
if let (Some(s), Some(e)) = (start, end) {
assert!(s < e, "start must be before end: {s:?} vs {e:?}");
} Try / catch
match client.request_trades(instrument_id, start, end, None).await {
Err(e) if e.to_string().contains("Invalid time range") => { /* fix bounds and retry */ }
other => other?,
} Prevention
- 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.
When it happens
Trigger: Calling a history/instruments request with start >= end (equal or inverted timestamps), e.g. passing the same datetime for both bounds or swapping them.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- instrument_type or instrument_id required for algo order que
- Exactly one of client_order_id or venue_order_id is required
- `tick_sz` is empty for {}
- `lot_sz` is empty for {}
- Empty underlying for {inst_id}: instrument may be pre-open o
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/25c0c93a1dd46fe2.
Report an issue: GitHub.