{"record":{"id":"c1c650fef064ae4a","repo":"risingwavelabs/risingwave","slug":"invalid-interval-0-expected-format-p-years-y-m","errorCode":null,"errorMessage":"Invalid interval: {0}, expected format P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S","messagePattern":"Invalid interval: (.+?), expected format P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S","errorType":"validation","errorClass":"IntervalParseError","httpStatus":null,"severity":"error","filePath":"src/common/src/types/interval.rs","lineNumber":1019,"sourceCode":"    fn write<W: std::fmt::Write>(&self, f: &mut W) -> std::fmt::Result {\n        write!(f, \"{self}\")\n    }\n\n    fn write_with_type<W: std::fmt::Write>(&self, ty: &DataType, f: &mut W) -> std::fmt::Result {\n        match ty {\n            DataType::Interval => self.write(f),\n            _ => unreachable!(),\n        }\n    }\n}\n\n/// Error type for parsing an [`Interval`].\n#[derive(thiserror::Error, Debug, thiserror_ext::Construct)]\npub enum IntervalParseError {\n    #[error(\"Invalid interval: {0}\")]\n    Invalid(String),\n\n    #[error(\n        \"Invalid interval: {0}, expected format P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S\"\n    )]\n    InvalidIso8601(String),\n\n    #[error(\"Invalid unit: {0}\")]\n    InvalidUnit(String),\n\n    #[error(\"{0}\")]\n    Uncategorized(String),\n}\n\ntype ParseResult<T> = std::result::Result<T, IntervalParseError>;\n\nimpl Interval {\n    pub fn as_iso_8601(&self) -> String {\n        // ISO pattern - PnYnMnDTnHnMnS\n        let years = self.months / 12;\n        let months = self.months % 12;","sourceCodeStart":1001,"sourceCodeEnd":1037,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/common/src/types/interval.rs#L1001-L1037","documentation":"IntervalParseError::InvalidIso8601 is raised when parsing an ISO 8601 duration string fails the strict P<n>Y<n>M<n>DT<n>H<n>M<n>S shape. The parser attempts each component and, if any step fails or overflow checks fail, reports the whole string as invalid ISO 8601.","triggerScenarios":"Strings like 'P1Y2M' handled fine but 'PT' (empty components), 'P' alone, '1Y2M' (missing leading 'P'), lowercase 'p1y', or values whose products overflow i64 (checked_mul/checked_add fail) in Interval::parse_iso8601.","commonSituations":"Feeding Java/Python datetime.timedelta-style strings ('1 day, 0:00:00') that only look ISO-like; decimal values in fields where the parser doesn't accept them; extremely large duration values overflowing i64 microseconds.","solutions":["Emit a strictly canonical ISO 8601 duration: starts with 'P', ordered Y/M/D then T H/M/S, uppercase.","Remove empty components (e.g. use 'PT0S' instead of 'PT').","Reduce the magnitude if component multiplication overflows i64 microseconds."],"exampleFix":"// before\nlet iv = Interval::parse_iso8601(\"p1y\")?;\n// after\nlet iv = Interval::parse_iso8601(\"P1Y\")?;","handlingStrategy":"validation","validationCode":"fn is_iso8601_duration(s: &str) -> bool {\n    regex::Regex::new(r\"^P(\\d+Y)?(\\d+M)?(\\d+D)?(T(\\d+H)?(\\d+M)?(\\d+(\\.\\d+)?S)?)?$\").unwrap()\n        .is_match(s) && s != \"P\"\n}","typeGuard":"fn looks_like_iso_duration(s: &str) -> bool {\n    s.starts_with('P') && s.len() > 1 && s.chars().all(|c| c.is_ascii_uppercase() || c.is_ascii_digit() || c == '.')\n}","tryCatchPattern":"let iv = Interval::parse_iso8601(s)\n    .map_err(|e| anyhow!(\"'{s}' is not a valid ISO 8601 duration: {e}\"))?;","preventionTips":["Always emit uppercase, canonical P..Y..M..DT..H..M..S strings.","Avoid empty component strings like 'PT'; use 'PT0S'.","Keep component magnitudes small enough to fit i64 microseconds after conversion."],"tags":["rust","interval","iso8601","parsing"],"backgroundTag":"invalid-duration-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"}