risingwavelabs/risingwave · error

failed to parse the timestamp

Error message

failed to parse the timestamp {ts} with the specified time zone {tz}

What it means

After resolving the timezone, to_batch_query_epoch converts the AS OF timestamp's Y/M/D H:M:S components via tz.with_ymd_and_hms. If the local time is ambiguous (DST overlap) or nonexistent (DST gap), chrono returns Ambiguous/None and this error is raised because a single unambiguous epoch cannot be computed.

Solutions

  1. Include an explicit UTC offset in the timestamp (e.g. '2024-03-10T02:30:00-05:00') to sidestep DST ambiguity.
  2. Choose a timestamp outside the DST transition window.
  3. Perform the time travel using epoch seconds (AsOf::TimestampNum) instead of a wall-clock string.

Example fix

// before
SELECT * FROM t AS OF TIMESTAMP '2024-03-10T02:30:00'; -- nonexistent local time
// after
SELECT * FROM t AS OF TIMESTAMP '2024-03-10T03:30:00-05:00';
Defensive patterns

Strategy: validation

Validate before calling

// avoid DST-ambiguous local times: use UTC or explicit offset
let dt = chrono::DateTime::parse_from_rfc3339("2024-03-10T02:30:00-05:00").unwrap();

Type guard

fn has_explicit_offset(s: &str) -> bool { chrono::DateTime::parse_from_rfc3339(s).map(|d| d.offset().fix().local_minus_utc() != 0).unwrap_or(false) }

Try / catch

match res {
    Err(e) if e.to_string().contains("with the specified time zone") => eprintln!("timestamp is DST-ambiguous/nonexistent; add explicit offset or use UTC"),
    other => other?,
}

Prevention

When it happens

Trigger: A time travel query with an AS OF timestamp string that falls inside a DST spring-forward gap or a fall-back overlap for the effective time zone, e.g. '2024-03-10T02:30:00' with a US timezone.

Common situations: Queries pinned to wall-clock times during daylight-saving transitions in the session time zone; timezoneless timestamps that land on nonexistent local times.

Understand the failure class

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/8075e8a5ea9170e9. Report an issue: GitHub.

Appendix: source

Thrown at src/frontend/src/optimizer/plan_node/utils.rs:540

        AsOf::TimestampString(ts) => {
            let date_time = speedate::DateTime::parse_str_rfc3339(ts)
                .map_err(|_e| anyhow!("failed to parse the timestamp"))?;
            if date_time.time.tz_offset.is_none() {
                // If the input does not specify a time zone, use the time zone set by the "SET TIME ZONE" command.
                risingwave_expr::expr_context::TIME_ZONE::try_with(|set_time_zone| {
                    let tz =
                        Timestamptz::lookup_time_zone(set_time_zone).map_err(|e| anyhow!(e))?;
                    match tz.with_ymd_and_hms(
                        date_time.date.year.into(),
                        date_time.date.month.into(),
                        date_time.date.day.into(),
                        date_time.time.hour.into(),
                        date_time.time.minute.into(),
                        date_time.time.second.into(),
                    ) {
                        MappedLocalTime::Single(d) => Ok(d.timestamp()),
                        MappedLocalTime::Ambiguous(_, _) | MappedLocalTime::None => {
                            Err(anyhow!(format!(
                                "failed to parse the timestamp {ts} with the specified time zone {tz}"
                            )))
                        }
                    }
                })??
            } else {
                date_time.timestamp_tz()
            }
        }
        AsOf::VersionNum(_) | AsOf::VersionString(_) => {
            return Err(ErrorCode::NotSupported(
                "AS OF VERSION is not supported".to_owned(),
                "please use AS OF TIMESTAMP".to_owned(),
            )
            .into());
        }
        AsOf::ProcessTimeWithInterval((value, leading_field)) => {
            let interval = Interval::parse_with_fields(

View on GitHub (pinned to 6469eb736d)