nautechsystems/nautilus_trader · error · anyhow::Error
Start date must be before end date
Error message
Start date must be before end date
What it means
request_bars validates that the optional start_date_time is strictly earlier than end_date_time. An equal or later start would produce an empty or inverted IB history window, so the call is rejected up front.
Source
Thrown at crates/adapters/interactive_brokers/src/historical/client.rs:243
&self,
bar_specifications: Vec<&str>,
end_date_time: Timestamp,
start_date_time: Option<Timestamp>,
duration: Option<&str>,
contracts: Option<Vec<Contract>>,
instrument_ids: Option<Vec<InstrumentId>>,
use_rth: bool,
timeout: u64,
) -> anyhow::Result<Vec<Bar>> {
// Validate inputs
if start_date_time.is_some() && duration.is_some() {
anyhow::bail!("Either start_date_time or duration should be provided, not both");
}
if let Some(start) = start_date_time
&& start >= end_date_time
{
anyhow::bail!("Start date must be before end date");
}
if let Some(duration) = duration {
duration.parse::<historical::Duration>().with_context(|| {
format!("duration must be in format: 'int S|D|W|M|Y', was '{duration}'")
})?;
}
let contracts = contracts.unwrap_or_default();
let instrument_ids = instrument_ids.unwrap_or_default();
if contracts.is_empty() && instrument_ids.is_empty() {
anyhow::bail!("Either contracts or instrument_ids must be provided");
}
// Convert instrument IDs to contracts using instrument provider
let mut all_contracts = contracts;
View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure start_date_time < end_date_time before calling; swap them if inverted.
- Truncate or floor start below the end boundary if they collide at a day edge.
- Drop start_date_time and pass a duration string instead if the exact window is flexible.
Example fix
// before client.request_bars(&["1-DAY-LAST"], end_ts, Some(end_ts), None, None, Some(ids), true, 60).await?; // after let start = end_ts - jiff::SignedDuration::from_hours(24); client.request_bars(&["1-DAY-LAST"], end_ts, Some(start), None, None, Some(ids), true, 60).await?;
Defensive patterns
Strategy: validation
Validate before calling
debug_assert!(start < end, "start must preced end");
if start >= end { return Err("invalid bar window: start >= end"); } Prevention
- Normalize all timestamps to UTC before comparing.
- Clamp start to end - 1 tick when they collide.
- Centralize window construction in one helper instead of ad-hoc timestamp math per call site.
When it happens
Trigger: Calling request_bars with start_date_time >= end_date_time (e.g. both set to the same day boundary, or start/end swapped).
Common situations: Computing start/end from UTC timestamps with timezone mix-ups; accidental argument swap; using 'now' for both fields; off-by-one when flooring end to the day while start carries a time-of-day.
Related errors
- Either start_date_time or duration should be provided, not b
- Either contracts or instrument_ids must be provided
- Cannot dispatch request, start {start_ns} was greater than e
- {e}
- {FAILED}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4db5498c954b0c7a.
Report an issue: GitHub.