risingwavelabs/risingwave · error · IntervalParseError
Invalid interval: {0}
Error message
Invalid interval: {0} What it means
IntervalParseError::Invalid is the generic failure of Interval's PostgreSQL-style text parser: the token stream did not yield a valid (years, months, days, usecs) tuple. Raised by parse_interval when a numeric buffer can't parse as i64 (convert_digit), an 'HH:MM:SS' segment is malformed, or the ':' appears without a preceding digit.
Source
Thrown at src/common/src/types/interval.rs:1016
}
impl ToText for crate::types::Interval {
fn write<W: std::fmt::Write>(&self, f: &mut W) -> std::fmt::Result {
write!(f, "{self}")
}
fn write_with_type<W: std::fmt::Write>(&self, ty: &DataType, f: &mut W) -> std::fmt::Result {
match ty {
DataType::Interval => self.write(f),
_ => unreachable!(),
}
}
}
/// Error type for parsing an [`Interval`].
#[derive(thiserror::Error, Debug, thiserror_ext::Construct)]
pub enum IntervalParseError {
#[error("Invalid interval: {0}")]
Invalid(String),
#[error(
"Invalid interval: {0}, expected format P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S"
)]
InvalidIso8601(String),
#[error("Invalid unit: {0}")]
InvalidUnit(String),
#[error("{0}")]
Uncategorized(String),
}
type ParseResult<T> = std::result::Result<T, IntervalParseError>;
impl Interval {
pub fn as_iso_8601(&self) -> String {View on GitHub (pinned to 6469eb736d)
Solutions
- Follow PostgreSQL interval syntax: '[<n> years] [<n> mons] [<n> days] [HH:MM:SS]'.
- Remove unsupported characters (commas, brackets); use space or unit-letter separators.
- For machine-readable exchange, use ISO 8601 duration format (P1Y2M3DT4H5M6S) which gets a more specific error.
Example fix
// before let iv: Interval = "1,000 days".parse()?; // after let iv: Interval = "1000 days".parse()?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_pg_style_interval(s: &str) -> bool {
s.split_whitespace().all(|tok| {
tok.chars().next().map(|c| c.is_ascii_digit() || c == '-' || c == '+' || c == ':' || c.is_ascii_alphabetic()).unwrap_or(false)
})
} Type guard
fn looks_like_interval(s: &str) -> bool {
!s.trim().is_empty()
&& s.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '+' | '.' | ':' | ' '))
} Try / catch
let iv = Interval::from_str(s)
.map_err(|e| anyhow!("invalid interval '{s}': {e}"))?; Prevention
- Stick to PostgreSQL interval syntax in literals and generated SQL.
- Avoid thousand separators and stray punctuation in numeric parts.
- Prefer ISO 8601 durations for machine-generated interval strings.
When it happens
Trigger: '1 year 2 foo' (unknown trailing token), 'abc' (non-numeric), ':' at start (' :30'), malformed clock part ('1:2:3:4'), or huge numbers overflowing i64 via Interval::from_str / parse_interval.
Common situations: Hand-written SQL intervals with typos ('2 weaks'); copying intervals from other systems whose syntax differs; values with separators the tokenizer doesn't accept (commas: '1,000 days').
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid interval: {0}, expected format P<years>Y<months>M<da
- Invalid unit: {0}
- {0}
- Can't cast string to date (expected format is YYYY-MM-DD)
- Can't cast string to time (expected format is HH:MM:SS[.D+{u
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/bc8319c8b2a5cdc2.
Report an issue: GitHub.