risingwavelabs/risingwave · error · InvalidParamsError

Can't cast string to date (expected format is YYYY-MM-DD)

Error message

Can't cast string to date (expected format is YYYY-MM-DD)

What it means

ErrorKind::ParseDate is thrown by Date::from_str when speedate's RFC3339 date parser fails on the input string. It means the string could not be interpreted as a calendar date; the expected format is YYYY-MM-DD.

Source

Thrown at src/common/src/types/datetime.rs:259

        let secs = (usecs / 1_000_000) as u32;
        let nano = (usecs % 1_000_000 * 1000) as u32;
        Time::from_num_seconds_from_midnight_uncheck(secs, nano)
    }
}

#[derive(Copy, Clone, Debug, Error)]
enum ErrorKind {
    #[error("Invalid date: days: {days}")]
    Date { days: i32 },
    #[error("Invalid time: secs: {secs}, nanoseconds: {nsecs}")]
    Time { secs: u32, nsecs: u32 },
    #[error("Invalid time: {value} {unit} is out of range for a time of day")]
    TimeOfDay { value: u64, unit: &'static str },
    #[error("Invalid datetime: seconds: {secs}, nanoseconds: {nsecs}")]
    DateTime { secs: i64, nsecs: u32 },
    #[error("Invalid datetime: {value} {unit} is out of range")]
    Timestamp { value: i64, unit: &'static str },
    #[error("Can't cast string to date (expected format is YYYY-MM-DD)")]
    ParseDate,
    #[error(
        "Can't cast string to time (expected format is HH:MM:SS[.D+{{up to 6 digits}}][Z] or HH:MM)"
    )]
    ParseTime,
    #[error(
        "Can't cast string to timestamp (expected format is YYYY-MM-DD HH:MM:SS[.D+{{up to 9 digits}}] or YYYY-MM-DD HH:MM or YYYY-MM-DD or ISO 8601 format)"
    )]
    ParseTimestamp,
}

#[derive(Debug, Error)]
#[error(transparent)]
pub struct InvalidParamsError(#[from] ErrorKind);

impl InvalidParamsError {
    pub fn date(days: i32) -> Self {
        ErrorKind::Date { days }.into()

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Reformat the input to YYYY-MM-DD before casting.
  2. Use a TO_DATE-style function with an explicit format mask if the source format is fixed but non-ISO.
  3. Trim whitespace/BOM from the input string first.

Example fix

// before
let d = Date::from_str("01/15/2024")?;
// after
let d = Date::from_str("2024-01-15")?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_iso_date(s: &str) -> bool {
    let s = s.trim();
    let b = s.as_bytes();
    b.len() == 10 && b[4] == b'-' && b[7] == b'-'
        && b.iter().enumerate().all(|(i, c)| i == 4 || i == 7 || c.is_ascii_digit())
}

Type guard

fn looks_like_date(s: &str) -> bool {
    regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap().is_match(s.trim())
}

Try / catch

let date = Date::from_str(s)
    .map_err(|e| anyhow!("'{s}' is not YYYY-MM-DD: {e}"))?;

Prevention

When it happens

Trigger: String literals cast to DATE in SQL (e.g. 'DATE abc', '2024/01/15', '2024-13-01' is range-valid but 'Jan 5 2024' is not) routed through Date::from_str via speedate::Date::parse_str_rfc3339.

Common situations: Loading CSV/JSON data with locale-formatted dates (MM/DD/YYYY); trailing whitespace or BOM characters; supplying time-only or datetime strings where a bare date is required.

Related errors


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