nautechsystems/nautilus_trader · warning

FX session boundary must be a unique local time

Error message

FX session boundary must be a unique local time

What it means

`fx_next_boundary` converts the target local date-time to a timestamp and calls `unambiguous()`, panicking if the local time is ambiguous — i.e. it occurs twice due to a DST fall-back transition in the session's timezone. The library refuses to guess which of the two instants is meant. This can be genuinely reachable if a session time equals an DST transition instant.

Source

Thrown at crates/trading/src/sessions.rs:157

    if local_now.time() > session_time {
        date = date
            .checked_add(Span::new().days(1))
            .expect("FX session date must be representable");
    }

    let weekend_days = match date.weekday() {
        Weekday::Saturday => 2,
        Weekday::Sunday => 1,
        _ => 0,
    };
    date = date
        .checked_add(Span::new().days(weekend_days))
        .expect("FX session date must be representable");

    timezone
        .to_ambiguous_timestamp(date.to_datetime(session_time))
        .unambiguous()
        .expect("FX session boundary must be a unique local time")
}

fn fx_prev_boundary(local_now: &Zoned, session_time: Time) -> Timestamp {
    let timezone = local_now.time_zone().clone();
    let mut date = local_now.date();

    if local_now.time() < session_time {
        date = date
            .checked_sub(Span::new().days(1))
            .expect("FX session date must be representable");
    }

    let weekend_days = match date.weekday() {
        Weekday::Saturday => 1,
        Weekday::Sunday => 2,
        _ => 0,
    };
    date = date

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Choose session times that avoid DST transition windows (never 00:30–02:30 local in zones observing DST, especially the 01:00–02:00 repeat hour).
  2. If a specific instant is required, resolve ambiguity explicitly with jiff's `earlier()`/`later()` on the `AmbiguousTimestamp` rather than using the panicking helper.
  3. Check whether the ambiguous date corresponds to a known DST transition and handle that day specially in your scheduling logic.
  4. Report the configuration that produced it upstream if the default session times are affected.

Example fix

// before
let boundary = fx_next_start(session, &now); // panics on ambiguous local time

// after (explicit disambiguation with jiff)
let ambiguous = tz.to_ambiguous_timestamp(date.to_datetime(session_time))?;
let boundary = ambiguous.earlier().ok_or_else(|| anyhow!("no earlier instant"))?.timestamp();
Defensive patterns

Strategy: validation

Validate before calling

// Avoid session times that can hit DST fall-back repeat windows (01:00-02:00 local)
fn session_time_dst_safe(t: jiff::civil::Time) -> bool {
    let h = t.hour();
    !(h == 1) // 01:xx local is the risky repeat hour in US/EU fall-back transitions
}

Try / catch

// Panics cannot be caught; if you need a 01:xx session time, resolve ambiguity yourself
let ambiguous = tz.to_ambiguous_timestamp(dt)?;
let ts = match ambiguous.earlier() {
    Some(z) => z.timestamp(),
    None => anyhow::bail!("session time is DST-ambiguous; pick a different session_time"),
};

Prevention

When it happens

Trigger: Calling `fx_next_start`/`fx_next_end` where the computed session local datetime (e.g. 05:00 Sydney) lands exactly inside a DST fall-back repeat window of the session timezone (Australia/Sydney, Asia/Tokyo, Europe/London, or America/New_York — only zones with fall-back transitions matter).

Common situations: Custom session times configured to exactly 1:00–2:00 AM local in DST-observing zones on transition days (e.g. 01:30 America/New_York on the November fall-back Sunday); unusual `ForexSession` variants with a `session_time` overlapping the transition.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/70b5155eb1cef85f. Report an issue: GitHub.