nautechsystems/nautilus_trader · error

bundled Asia/Tokyo timezone

Error message

bundled Asia/Tokyo timezone

What it means

Identical to the Sydney case: the Tokyo session's `LazyLock` resolves `Asia/Tokyo` via `get_timezone` and panics on failure. The library assumes the tz database is available (bundled at build time), so an error indicates the timezone lookup layer is misconfigured. It fires the first time any Tokyo FX session boundary is computed.

Source

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

//! - Sydney Session    0700-1600 (Australia / Sydney)
//! - Tokyo Session     0900-1800 (Asia / Tokyo)
//! - London Session    0800-1600 (Europe / London)
//! - New York Session  0800-1700 (America / New York)

use std::sync::LazyLock;

use jiff::{
    Span, Timestamp, Zoned,
    civil::{Time, Weekday},
    tz::TimeZone,
};
use nautilus_core::datetime::get_timezone;
use strum::{Display, EnumIter, EnumString, FromRepr};

static SYDNEY_TIMEZONE: LazyLock<TimeZone> =
    LazyLock::new(|| get_timezone("Australia/Sydney").expect("bundled Australia/Sydney timezone"));
static TOKYO_TIMEZONE: LazyLock<TimeZone> =
    LazyLock::new(|| get_timezone("Asia/Tokyo").expect("bundled Asia/Tokyo timezone"));
static LONDON_TIMEZONE: LazyLock<TimeZone> =
    LazyLock::new(|| get_timezone("Europe/London").expect("bundled Europe/London timezone"));
static NEW_YORK_TIMEZONE: LazyLock<TimeZone> =
    LazyLock::new(|| get_timezone("America/New_York").expect("bundled America/New_York timezone"));

/// Represents a major Forex market session based on trading hours.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, FromRepr, EnumIter, EnumString, Display)]
#[strum(ascii_case_insensitive)]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
#[cfg_attr(
    feature = "python",
    pyo3::pyclass(
        eq,
        eq_int,
        module = "nautilus_trader.trading",
        from_py_object,
        rename_all = "SCREAMING_SNAKE_CASE"
    )

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Enable the bundled timezone database (chrono-tz / tzdb feature) in the datetime dependency.
  2. Install tzdata in the runtime image (`apt-get install tzdata` / `apk add tzdata`).
  3. Check `TZDIR`/zoneinfo configuration if the resolver reads the system database.
  4. Rebuild after dependency or feature changes so bundled tz data is embedded.

Example fix

// before (Dockerfile)
FROM scratch
COPY target/release/app /

// after
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y tzdata && rm -rf /var/lib/apt/lists/*
COPY target/release/app /
Defensive patterns

Strategy: fallback

Validate before calling

fn tzdata_available() -> bool {
    std::path::Path::new("/usr/share/zoneinfo/Asia/Tokyo").exists()
}

Try / catch

// Panics cannot be caught in Rust; fail fast at startup instead
assert!(tzdata_available(), "Asia/Tokyo unresolvable: install tzdata or enable bundled tzdb");

Prevention

When it happens

Trigger: First call touching `TOKYO_TIMEZONE` (Tokyo session start/end/boundary helpers) when `get_timezone("Asia/Tokyo")` cannot resolve the IANA name.

Common situations: Minimal Docker images without tzdata; builds where the bundled chrono-tz tables were feature-gated out; environments whose `TZDIR` points at an incomplete zoneinfo directory.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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