{"record":{"id":"13e138c9a8022357","repo":"risingwavelabs/risingwave","slug":"can-t-cast-string-to-date-expected-format-is-yyyy","errorCode":null,"errorMessage":"Can't cast string to date (expected format is YYYY-MM-DD)","messagePattern":"Can't cast string to date \\(expected format is YYYY-MM-DD\\)","errorType":"validation","errorClass":"InvalidParamsError","httpStatus":null,"severity":"error","filePath":"src/common/src/types/datetime.rs","lineNumber":259,"sourceCode":"        let secs = (usecs / 1_000_000) as u32;\n        let nano = (usecs % 1_000_000 * 1000) as u32;\n        Time::from_num_seconds_from_midnight_uncheck(secs, nano)\n    }\n}\n\n#[derive(Copy, Clone, Debug, Error)]\nenum ErrorKind {\n    #[error(\"Invalid date: days: {days}\")]\n    Date { days: i32 },\n    #[error(\"Invalid time: secs: {secs}, nanoseconds: {nsecs}\")]\n    Time { secs: u32, nsecs: u32 },\n    #[error(\"Invalid time: {value} {unit} is out of range for a time of day\")]\n    TimeOfDay { value: u64, unit: &'static str },\n    #[error(\"Invalid datetime: seconds: {secs}, nanoseconds: {nsecs}\")]\n    DateTime { secs: i64, nsecs: u32 },\n    #[error(\"Invalid datetime: {value} {unit} is out of range\")]\n    Timestamp { value: i64, unit: &'static str },\n    #[error(\"Can't cast string to date (expected format is YYYY-MM-DD)\")]\n    ParseDate,\n    #[error(\n        \"Can't cast string to time (expected format is HH:MM:SS[.D+{{up to 6 digits}}][Z] or HH:MM)\"\n    )]\n    ParseTime,\n    #[error(\n        \"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)\"\n    )]\n    ParseTimestamp,\n}\n\n#[derive(Debug, Error)]\n#[error(transparent)]\npub struct InvalidParamsError(#[from] ErrorKind);\n\nimpl InvalidParamsError {\n    pub fn date(days: i32) -> Self {\n        ErrorKind::Date { days }.into()","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/common/src/types/datetime.rs#L241-L277","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Reformat the input to YYYY-MM-DD before casting.","Use a TO_DATE-style function with an explicit format mask if the source format is fixed but non-ISO.","Trim whitespace/BOM from the input string first."],"exampleFix":"// before\nlet d = Date::from_str(\"01/15/2024\")?;\n// after\nlet d = Date::from_str(\"2024-01-15\")?;","handlingStrategy":"validation","validationCode":"fn is_iso_date(s: &str) -> bool {\n    let s = s.trim();\n    let b = s.as_bytes();\n    b.len() == 10 && b[4] == b'-' && b[7] == b'-'\n        && b.iter().enumerate().all(|(i, c)| i == 4 || i == 7 || c.is_ascii_digit())\n}","typeGuard":"fn looks_like_date(s: &str) -> bool {\n    regex::Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}$\").unwrap().is_match(s.trim())\n}","tryCatchPattern":"let date = Date::from_str(s)\n    .map_err(|e| anyhow!(\"'{s}' is not YYYY-MM-DD: {e}\"))?;","preventionTips":["Normalize all date inputs to ISO YYYY-MM-DD at ingestion.","Trim whitespace/BOM before casting.","Use explicit format-mask parsing for locale-specific sources."],"tags":["rust","date","parsing","sql-cast"],"backgroundTag":"invalid-date-format","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}