{"record":{"id":"d2cb695c6d3235ba","repo":"nautechsystems/nautilus_trader","slug":"invalid-execution-time-format-time-str","errorCode":null,"errorMessage":"Invalid execution time format: {time_str}","messagePattern":"Invalid execution time format: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/execution/parse.rs","lineNumber":412,"sourceCode":"/// DST fall-back folds resolve to the earliest matching instant.\npub fn parse_execution_time(time_str: &str) -> anyhow::Result<UnixNanos> {\n    const NAIVE_FORMAT: &str = \"%Y%m%d %H:%M:%S\";\n\n    // Hyphenated, space-less form (e.g. \"20250225-15:15:00\") is always UTC.\n    if !time_str.contains(' ') {\n        let normalized = time_str.replace('-', \" \");\n        let dt = DateTime::strptime(NAIVE_FORMAT, &normalized).map_err(|e| {\n            anyhow::anyhow!(\"Failed to parse execution timestamp '{time_str}': {e}\")\n        })?;\n        return datetime_to_unix_nanos(Offset::UTC.to_timestamp(dt)?, time_str);\n    }\n\n    // Split into at most three parts: date, time, and optional timezone token.\n    // The timezone token itself never contains a space, so `splitn(3, ' ')`\n    // correctly groups IANA names such as \"America/New_York\".\n    let mut parts = time_str.splitn(3, ' ');\n    let (Some(date), Some(time)) = (parts.next(), parts.next()) else {\n        anyhow::bail!(\"Invalid execution time format: {time_str}\");\n    };\n    let tz_str = parts.next().unwrap_or(\"\").trim();\n\n    let naive_str = format!(\"{date} {time}\");\n    let dt = DateTime::strptime(NAIVE_FORMAT, &naive_str)\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse execution timestamp '{time_str}': {e}\"))?;\n\n    let utc = if tz_str.is_empty() {\n        Offset::UTC.to_timestamp(dt)?\n    } else {\n        localize_with_zone(dt, tz_str, time_str)?\n    };\n\n    datetime_to_unix_nanos(utc, time_str)\n}\n\n/// Localize a naive timestamp against an IB timezone token and convert to UTC.\n///","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/execution/parse.rs#L394-L430","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet time_str = \"20260908\"; // missing time part\nparse_execution_time(time_str)?;\n// after\nlet time_str = \"20260908 14:30:05\"; // date + time (+ optional tz)\nparse_execution_time(time_str)?;","handlingStrategy":"validation","validationCode":"fn looks_like_ib_execution_time(s: &str) -> bool {\n    // Expect at least 'YYYYMMDD HH:MM:SS' (optionally plus a timezone token)\n    let mut parts = s.split(' ');\n    let date = parts.next().unwrap_or(\"\");\n    let time = parts.next().unwrap_or(\"\");\n    date.len() == 8 && date.chars().all(|c| c.is_ascii_digit())\n        && time.len() >= 8 && time.contains(':')\n}","typeGuard":null,"tryCatchPattern":"match parse_execution_time(time_str) {\n    Err(e) if e.to_string().starts_with(\"Invalid execution time format\") => {\n        log::warn!(\"skipping fill with malformed timestamp: {time_str:?}\");\n        // skip or substitute a default before retrying\n    }\n    other => other?,\n}","preventionTips":["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"],"tags":["parsing","timestamp","format","execution-report"],"backgroundTag":"invalid-date-format","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"}