{"record":{"id":"1e313611645390ed","repo":"nautechsystems/nautilus_trader","slug":"invalid-expiry-format","errorCode":null,"errorMessage":"Invalid expiry format: {}","messagePattern":"Invalid expiry format: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/providers/parse.rs","lineNumber":148,"sourceCode":"            let time_part = parts[1];\n            let year = &date_part[0..4];\n            let month = &date_part[4..6];\n            let day = &date_part[6..8];\n\n            let time_parts: Vec<&str> = time_part.split(':').collect();\n            let hour = time_parts.first().unwrap_or(&\"0\").parse::<u8>()?;\n            let minute = time_parts.get(1).unwrap_or(&\"0\").parse::<u8>()?;\n            let second = time_parts.get(2).unwrap_or(&\"0\").parse::<u8>()?;\n\n            let date = time::Date::from_calendar_date(\n                year.parse()?,\n                time::Month::try_from(month.parse::<u8>()?)?,\n                day.parse()?,\n            )?;\n            let time_obj = time::Time::from_hms(hour, minute, second)?;\n            time::PrimitiveDateTime::new(date, time_obj)\n        } else {\n            anyhow::bail!(\"Invalid expiry format: {}\", expiry);\n        }\n    };\n\n    // Treat the parsed expiry timestamp as UTC. NautilusTrader expects IB timestamps\n    // to be configured and interpreted in UTC.\n    let offset_dt = dt.assume_utc();\n    let nanos = offset_dt.unix_timestamp_nanos();\n    Ok(UnixNanos::new(nanos as u64))\n}\n\n/// Parse an IB ContractDetails to a Nautilus instrument.\n///\n/// # Errors\n///\n/// Returns an error if parsing fails.\npub fn parse_ib_contract_to_instrument(\n    details: &ibapi::contracts::ContractDetails,\n    instrument_id: InstrumentId,","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/providers/parse.rs#L130-L166","documentation":"expiry_timestring_to_unix_nanos accepts only two expiry formats: plain YYYYMMDD (8 chars) and a datetime form like YYYYMMDD HH:MM:SS (optionally with a timezone suffix). Any other string shape cannot be parsed into a date/time and triggers this error with the raw input.","triggerScenarios":"parse_futures_contract or parse_option_contract passes an expiry string that is neither 8-char YYYYMMDD nor matches the datetime format IB sometimes returns (unexpected separators, partial dates, or a foreign format).","commonSituations":"Custom/mock data using ISO format like 2026-06-19, timezone variants the parser doesn't handle, truncated strings, or IB format changes across API versions.","solutions":["Normalize the expiry to YYYYMMDD (or 'YYYYMMDD HH:MM:SS') before calling the parser.","Strip/reformat ISO-style strings (2026-06-19 -> 20260619) at the data source boundary.","Check the IB API version is producing the documented expiry format; upgrade or add parsing for the new variant upstream.","Log the offending string in the message and fix that specific field in your data pipeline."],"exampleFix":"// before: ISO format fails\nexpiry_timestring_to_unix_nanos(\"2026-06-19\", None)?;\n// after: normalized IB format\nexpiry_timestring_to_unix_nanos(\"20260619\", None)?;","handlingStrategy":"validation","validationCode":"fn expiry_is_parseable(expiry: &str) -> bool {\n    expiry.len() == 8 && expiry.chars().all(|c| c.is_ascii_digit())\n        || (expiry.len() >= 19 && expiry.as_bytes()[8] == b' ')\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize all expiry strings to YYYYMMDD (or YYYYMMDD HH:MM:SS) upstream","Don't assume ISO formats — IB uses compact YYYYMMDD","Add regression tests for each expiry format your data source emits"],"tags":["interactive-brokers","parsing","expiry","date-format"],"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-14T00:17:10.932Z"}