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
- Rewrite the AS OF timestamp as a valid RFC3339 string, e.g. '2024-01-01T10:00:00Z'.
- Use AS OF TIMESTAMP with a numeric epoch value (AsOf::TimestampNum) instead of a string.
- 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
- Always emit RFC3339 (with T separator and offset) for AS OF TIMESTAMP strings.
- Prefer numeric epoch AS OF values to avoid string parsing entirely.
- Validate timestamps in the SQL-generating layer before execution.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- anyhow!(e)
- failed to parse the interval
- failed to parse the timestamp
- invalid timestamp
- number or string
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)