databendlabs/databend · info

clamped timestamp is inside the chrono range

Error message

clamped timestamp is inside the chrono range

What it means

timestamp_from_micros clamps the input microseconds to TIMESTAMP_MIN..TIMESTAMP_MAX, then converts to a chrono DateTime via DateTime::<Utc>::from_timestamp, expecting the clamped value to be representable. The panic fires only if the constants TIMESTAMP_MIN/TIMESTAMP_MAX themselves are outside what chrono's from_timestamp accepts — an internal invariant; the clamp is designed so this cannot trigger with correct constants.

Solutions

  1. No caller action required; verify TIMESTAMP_MIN/TIMESTAMP_MAX stay within chrono's representable range after upgrades.
  2. If seen, pin/check the chrono version compatibility of DateTime::<Utc>::from_timestamp.
Defensive patterns

Strategy: validation

Validate before calling

// Not required; the function clamps internally. No caller guard needed.
let dt = timestamp_from_micros(micros, tz);

Prevention

When it happens

Trigger: Practically unreachable for callers; would only fire if TIMESTAMP_MIN/TIMESTAMP_MAX constants were changed to values outside chrono's supported range (seconds beyond roughly year ±262143).

Common situations: Only during refactors of the timestamp range constants or a chrono major-version upgrade changing from_timestamp's accepted bounds.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/344ca069c8bd1951. Report an issue: GitHub.

Appendix: source

Thrown at src/query/expression/src/types/timestamp.rs:63

/// Converting that local date to SQL DATE must separately validate DATE_MIN/MAX.
/// INTERVAL arithmetic reports out-of-range results; other paths retain their
/// existing overflow policies. Display conversion clamps to these bounds.
/// 0001-01-01 00:00:00.000000 UTC
pub const TIMESTAMP_MIN: i64 = -62_135_596_800_000_000;
/// 9999-12-31 23:59:59.999999 UTC
pub const TIMESTAMP_MAX: i64 = 253_402_300_799_999_999;

pub const MICROS_PER_SEC: i64 = 1_000_000;
pub const MICROS_PER_MILLI: i64 = 1_000;

/// Clamp to the SQL UTC bounds before converting for display.
/// Chrono has room for local year 0/10000 at these boundaries.
pub fn timestamp_from_micros(micros: impl AsPrimitive<i64>, tz: &Tz) -> DateTime<Tz> {
    let micros = micros.as_().clamp(TIMESTAMP_MIN, TIMESTAMP_MAX);
    let seconds = micros.div_euclid(MICROS_PER_SEC);
    let subsec = micros.rem_euclid(MICROS_PER_SEC) as u32;
    DateTime::<Utc>::from_timestamp(seconds, subsec * 1_000)
        .expect("clamped timestamp is inside the chrono range")
        .with_timezone(tz)
}

pub const PRECISION_MICRO: u8 = 6;
pub const PRECISION_MILLI: u8 = 3;
pub const PRECISION_SEC: u8 = 0;

/// Preserve the legacy conversion policy: either bound overflow maps to TIMESTAMP_MIN.
#[inline]
pub fn clamp_timestamp(micros: &mut i64) {
    if !(TIMESTAMP_MIN..=TIMESTAMP_MAX).contains(micros) {
        *micros = TIMESTAMP_MIN;
    }
}

/// Validate the final SQL instant, not its local calendar year.
#[inline]
pub fn check_timestamp(micros: i64) -> Result<i64, String> {

View on GitHub (pinned to 288d84d76e)