{"record":{"id":"ffb7fd0a8ce35820","repo":"risingwavelabs/risingwave","slug":"invalid-time-value-unit-is-out-of-range-for-a","errorCode":null,"errorMessage":"Invalid time: {value} {unit} is out of range for a time of day","messagePattern":"Invalid time: (.+?) (.+?) is out of range for a time of day","errorType":"validation","errorClass":"InvalidParamsError","httpStatus":null,"severity":"error","filePath":"src/common/src/types/datetime.rs","lineNumber":253,"sourceCode":"/// let time = Time::from(interval);\n/// assert_eq!(time, Time::from_str(\"23:58:58.999997\").unwrap());\n/// ```\nimpl From<Interval> for Time {\n    fn from(interval: Interval) -> Self {\n        let usecs = interval.usecs_of_day();\n        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)]","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/common/src/types/datetime.rs#L235-L271","documentation":"ErrorKind::TimeOfDay in risingwave_common::types::datetime is raised when a nanosecond or microsecond count since midnight is too large to represent a valid TIME value (>= 86,400 seconds per day). Time::with_nano and Time::with_micro reject such values so that the TIME cast stays lossless. It surfaces as an InvalidParamsError.","triggerScenarios":"Calling Time::with_nano(nano) with nano >= 86_400 * 1_000_000_000, or Time::with_micro(micro) with micro >= 86_400 * 1_000_000; also hit indirectly when deserializing a Time column from protobuf (Time::from_protobuf) with a corrupt or out-of-range buffer.","commonSituations":"Ingesting source data where a duration-like column (elapsed ms/us) is accidentally cast to TIME; arithmetic on times that overflows midnight; corrupted or misaligned protobuf payloads on the wire.","solutions":["Check the value is < 86_400 * 1_000_000 (micros) or < 86_400 * 1_000_000_000 (nanos) before constructing the Time.","If the value is a duration, keep it as an Interval instead of casting to TIME.","Wrap midnight overflow with modulo (value % MICROS_PER_DAY) if wrapping semantics are intended."],"exampleFix":"// before\nlet t = Time::with_micro(micros_since_midnight)?;\n// after\nlet t = Time::with_micro(micros_since_midnight % 86_400_000_000)?;","handlingStrategy":"validation","validationCode":"const MICROS_PER_DAY: u64 = 86_400 * 1_000_000;\nfn can_be_time_micros(micros: u64) -> bool { micros < MICROS_PER_DAY }","typeGuard":"fn is_valid_time_of_day(value: u64, unit_us: bool) -> bool {\n    if unit_us { value < 86_400_000_000 } else { value < 86_400_000_000_000 }\n}","tryCatchPattern":"match Time::with_micro(micros) {\n    Ok(t) => t,\n    Err(e) => { log::warn!(\"time-of-day overflow: {e}\"); Time::with_micro(micros % 86_400_000_000).unwrap() }\n}","preventionTips":["Never cast duration columns directly to TIME; use INTERVAL.","Range-check values against 86_400_000_000 micros before constructing.","Watch protobuf decoding paths - validate buffer lengths and provenance."],"tags":["rust","time","value-out-of-range","risingwave"],"backgroundTag":"value-out-of-range","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"}