risingwavelabs/risingwave · error

failed to parse the timestamp

Error message

failed to parse the timestamp

What it means

In to_batch_query_epoch, when an AS OF time travel clause uses a timestamp string (AsOf::TimestampString), it is parsed with speedate's RFC3339 parser. If the string is not valid RFC3339, the parse error is replaced with this generic "failed to parse the timestamp" error.

Solutions

  1. Rewrite the AS OF timestamp as a valid RFC3339 string, e.g. '2024-01-01T10:00:00Z'.
  2. Use AS OF TIMESTAMP with a numeric epoch value (AsOf::TimestampNum) instead of a string.
  3. Check the application code generating the timestamp to ensure it emits RFC3339 with offset.

Example fix

// before
SELECT * FROM t AS OF TIMESTAMP '2024/01/01 10:00';
// after
SELECT * FROM t AS OF TIMESTAMP '2024-01-01T10:00:00Z';
Defensive patterns

Strategy: validation

Validate before calling

// client-side check before issuing time travel query
let ts = "2024-01-01T10:00:00Z";
assert!(chrono::DateTime::parse_from_rfc3339(ts).is_ok(), "AS OF TIMESTAMP must be RFC3339");

Type guard

fn is_rfc3339(s: &str) -> bool { chrono::DateTime::parse_from_rfc3339(s).is_ok() }

Try / catch

match res {
    Err(e) if e.to_string().contains("failed to parse the timestamp") => eprintln!("AS OF TIMESTAMP must be an RFC3339 string, e.g. 2024-01-01T10:00:00Z"),
    other => other?,
}

Prevention

When it happens

Trigger: Executing a time travel query such as `SELECT ... FROM t AS OF TIMESTAMP 'not-a-date'` where the string fails speedate::DateTime::parse_str_rfc3339; also via lookup join AS OF or vector index nearest AS OF clauses that carry a TimestampString.

Common situations: Typos or non-RFC3339 formats like '2024-01-01 10:00:00' (space instead of T), locale-formatted dates, or Unix epoch numbers quoted as strings.

Understand the failure class

Related errors


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

Appendix: source

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

}

pub fn to_batch_query_epoch(a: &Option<AsOf>) -> Result<Option<PbBatchQueryEpoch>> {
    let Some(a) = a else {
        return Ok(None);
    };
    Feature::TimeTravel.check_available()?;
    let timestamp = match a {
        AsOf::ProcessTime | AsOf::ProcessTimeBroadcast => {
            return Err(ErrorCode::NotSupported(
                "AS OF PROCTIME is not supported".to_owned(),
                "please use AS OF TIMESTAMP".to_owned(),
            )
            .into());
        }
        AsOf::TimestampNum(ts) => *ts,
        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}"
                            )))

View on GitHub (pinned to 6469eb736d)