nautechsystems/nautilus_trader · error
Failed to parse ISO 8601 string '{date_string}': {e}
Error message
Failed to parse ISO 8601 string '{date_string}': {e} What it means
iso8601_to_unix_nanos delegates to `str::parse::<UnixNanos>`, and when parsing fails it wraps the underlying parse error with the offending string. It means the input string was not recognized as a valid ISO 8601 / RFC 3339 timestamp (or was out of range for UnixNanos). The library throws it because a free-form string cannot be safely converted to a nanosecond UNIX timestamp without strict validation.
Source
Thrown at crates/core/src/datetime.rs:454
///
/// - `date_string`: The ISO 8601 formatted date string to parse
///
/// # Returns
///
/// Returns `Ok(UnixNanos)` if the string is successfully parsed, or an error if the format
/// is invalid or the timestamp is out of range.
///
/// # Errors
///
/// Returns an error if:
/// - The string format is not a valid ISO 8601 format
/// - The timestamp is out of range for `UnixNanos`
/// - The date/time values are invalid
#[inline]
pub fn iso8601_to_unix_nanos(date_string: &str) -> anyhow::Result<UnixNanos> {
date_string
.parse::<UnixNanos>()
.map_err(|e| anyhow::anyhow!("Failed to parse ISO 8601 string '{date_string}': {e}"))
}
/// Converts a UNIX nanoseconds timestamp to an ISO 8601 (RFC 3339) format string
/// with millisecond precision.
///
/// All [`UnixNanos`] values are representable by this formatter.
#[inline]
#[must_use]
pub fn unix_nanos_to_iso8601_millis(unix_nanos: UnixNanos) -> String {
let parts = split_unix_nanos(unix_nanos);
let mut out = String::with_capacity(24);
push_iso8601_prefix(
&mut out,
parts.year,
parts.month,
parts.day,
parts.hour,View on GitHub (pinned to 18893faf8b)
Solutions
- Validate and normalize the string to RFC 3339 before calling, e.g. ensure a 'T' separator and a 'Z'/offset suffix.
- Print the inner parse error (it is included in the message) to see exactly which part of the format jiff rejected.
- If the value is a plain epoch number, parse it as an integer and construct UnixNanos directly instead of ISO parsing.
- For pre-1970 timestamps, switch to a signed representation at the call site; UnixNanos is u64 and cannot hold them.
Example fix
// before
let ns = iso8601_to_unix_nanos("2024-01-01 00:00:00")?; // no offset -> parse error
// after
let ns = iso8601_to_unix_nanos("2024-01-01T00:00:00Z")?; Defensive patterns
Strategy: validation
Validate before calling
// Rust: validate RFC 3339 shape before calling
fn is_rfc3339(s: &str) -> bool {
s.len() >= 20 && s.as_bytes()[10] == b'T' && (s.ends_with('Z') || s.contains('+') || s.contains('-'))
}
if !is_rfc3339(date_string) { /* normalize or reject */ } Try / catch
match iso8601_to_unix_nanos(s) {
Ok(ns) => ns,
Err(e) => { log::warn!("bad timestamp {s}: {e}"); return Err(e); }
} Prevention
- Always emit timestamps as RFC 3339 with explicit UTC offset ('Z').
- Never pass pre-1970 dates into UnixNanos-based APIs.
- Log the raw string alongside the error for quick diagnosis.
When it happens
Trigger: Calling iso8601_to_unix_nanos (or iso_to_unix_nanos) with a malformed string: missing timezone (e.g. "2024-01-01 00:00:00" without offset), wrong separator (space instead of 'T' when required), fractional precision beyond supported format, empty string, or a timestamp outside the u64-nanosecond range (pre-1970 dates).
Common situations: Feeding user-supplied or config-file datetimes straight in; log timestamps in non-RFC3339 formats; Python callers passing datetime.strftime output without timezone; data from exchanges using "YYYYMMDD" or epoch-millis strings; negative/pre-epoch dates that overflow UnixNanos (u64).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid scientific notation exponent '{exponent}': must be a
- {FAILED}: {e}
- {FAILED}: {e}
- missing persistence type for order update {}
- Order missing order_qty and cannot reconstruct (order_id={},
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4870858f66211fdf.
Report an issue: GitHub.