nautechsystems/nautilus_trader · error · anyhow::Error
Invalid execution time format: {time_str}
Error message
Invalid execution time format: {time_str} What it means
IB execution timestamps must contain both a date and a time component separated by a space (with an optional third token for the timezone, e.g. an IANA name like America/New_York). parse_execution_time splits the string into at most three space-separated parts and bails with this error when fewer than two parts (date + time) are present.
Source
Thrown at crates/adapters/interactive_brokers/src/execution/parse.rs:412
/// DST fall-back folds resolve to the earliest matching instant.
pub fn parse_execution_time(time_str: &str) -> anyhow::Result<UnixNanos> {
const NAIVE_FORMAT: &str = "%Y%m%d %H:%M:%S";
// Hyphenated, space-less form (e.g. "20250225-15:15:00") is always UTC.
if !time_str.contains(' ') {
let normalized = time_str.replace('-', " ");
let dt = DateTime::strptime(NAIVE_FORMAT, &normalized).map_err(|e| {
anyhow::anyhow!("Failed to parse execution timestamp '{time_str}': {e}")
})?;
return datetime_to_unix_nanos(Offset::UTC.to_timestamp(dt)?, time_str);
}
// Split into at most three parts: date, time, and optional timezone token.
// The timezone token itself never contains a space, so `splitn(3, ' ')`
// correctly groups IANA names such as "America/New_York".
let mut parts = time_str.splitn(3, ' ');
let (Some(date), Some(time)) = (parts.next(), parts.next()) else {
anyhow::bail!("Invalid execution time format: {time_str}");
};
let tz_str = parts.next().unwrap_or("").trim();
let naive_str = format!("{date} {time}");
let dt = DateTime::strptime(NAIVE_FORMAT, &naive_str)
.map_err(|e| anyhow::anyhow!("Failed to parse execution timestamp '{time_str}': {e}"))?;
let utc = if tz_str.is_empty() {
Offset::UTC.to_timestamp(dt)?
} else {
localize_with_zone(dt, tz_str, time_str)?
};
datetime_to_unix_nanos(utc, time_str)
}
/// Localize a naive timestamp against an IB timezone token and convert to UTC.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Check the raw IB message and ensure the execution time field contains both date and time, e.g. '20260908 10:15:30 US/Eastern'.
- Log/inspect time_str shown in the error to see exactly what the adapter received; fix the upstream parsing that produced a truncated value.
- Handle empty timestamps before calling by defaulting or skipping the fill.
- If IB changed its report format, update NAIVE_FORMAT in parse.rs and the splitting logic accordingly.
Example fix
// before let time_str = "20260908"; // missing time part parse_execution_time(time_str)?; // after let time_str = "20260908 14:30:05"; // date + time (+ optional tz) parse_execution_time(time_str)?;
Defensive patterns
Strategy: validation
Validate before calling
fn looks_like_ib_execution_time(s: &str) -> bool {
// Expect at least 'YYYYMMDD HH:MM:SS' (optionally plus a timezone token)
let mut parts = s.split(' ');
let date = parts.next().unwrap_or("");
let time = parts.next().unwrap_or("");
date.len() == 8 && date.chars().all(|c| c.is_ascii_digit())
&& time.len() >= 8 && time.contains(':')
} Try / catch
match parse_execution_time(time_str) {
Err(e) if e.to_string().starts_with("Invalid execution time format") => {
log::warn!("skipping fill with malformed timestamp: {time_str:?}");
// skip or substitute a default before retrying
}
other => other?,
} Prevention
- Validate the raw IB report fields for non-empty date+time before parsing
- Normalize timestamps to 'YYYYMMDD HH:MM:SS[ tz]' as early as possible in ingestion
- Log the offending string (already included in the error) to spot upstream format changes
- Add unit tests covering empty, date-only, and full timestamp inputs
When it happens
Trigger: Passing a timestamp string to parse_execution_time (directly or via parse_historical_fill_report, handle_execution_data, pending-combo fill building, or leg fill generation) that lacks a space-separated date and time — e.g. an empty string, only a date like '20260908', or a malformed value.
Common situations: Empty or missing execution time fields in IB fill/execution reports; broker responses using an unexpected format; concatenation bugs producing a single token; regional IB report formats differing from the expected YYYYMMDD HH:MM:SS layout.
Related errors
- Execution timestamp '{time_str}' is non-existent in timezone
- Negative nanosecond timestamp from: {timestamp}
- Venue '{venue_str}' is not a DEX venue (expected format 'Cha
- invalid negative Binance {field} timestamp: {value}
- Binance {field} timestamp is outside the UnixNanos range: {v
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d2cb695c6d3235ba.
Report an issue: GitHub.