risingwavelabs/risingwave · error · IntervalParseError
{0}
Error message
{0} What it means
IntervalParseError::Uncategorized carries a free-form message for tokenizer-level failures in parse_interval that don't fit the other variants - notably an illegal character at a given offset ('Invalid character at offset N in <s>: <c>. Only support digit or alphabetic now').
Source
Thrown at src/common/src/types/interval.rs:1027
}
}
}
/// 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 {
// ISO pattern - PnYnMnDTnHnMnS
let years = self.months / 12;
let months = self.months % 12;
let days = self.days;
let secs_fract = (self.usecs % USECS_PER_SEC).abs();
let total_secs = (self.usecs / USECS_PER_SEC).abs();
let hours = total_secs / 3600;
let minutes = (total_secs / 60) % 60;
let seconds = total_secs % 60;
let mut buf = [0u8; 7];
let fract_str = if secs_fract != 0 {View on GitHub (pinned to 6469eb736d)
Solutions
- Remove unsupported characters; only digits, ASCII letters, whitespace, '-', '+', '.', ':' are allowed.
- Replace comma thousand-separators with plain digits.
- Sanitize/trim the input string before parsing if it comes from user text.
Example fix
// before let iv: Interval = "2 days, 3 hours".parse()?; // after let iv: Interval = "2 days 3 hours".parse()?;
Defensive patterns
Strategy: validation
Validate before calling
fn has_only_allowed_chars(s: &str) -> bool {
s.chars().all(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace() || matches!(c, '-' | '+' | '.' | ':'))
} Type guard
fn is_clean_interval_string(s: &str) -> bool {
!s.is_empty() && s.is_ascii() && s.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '+' | '.' | ':' | ' '))
} Try / catch
let iv = Interval::from_str(s)
.map_err(|e| anyhow!("cannot tokenize interval '{s}': {e}"))?; Prevention
- Sanitize user-supplied interval text: remove commas, brackets, punctuation.
- Check inputs are ASCII - unicode lookalikes are rejected by the tokenizer.
- Reject or clean interval strings at the application boundary before SQL construction.
When it happens
Trigger: Interval strings containing punctuation other than '-', '+', '.', ':', digits, letters and whitespace: e.g. '1h 30m!' , '2 days, 3 hours', parentheses, or non-ASCII unit names.
Common situations: Copy-pasted interval text with commas or trailing punctuation; templated SQL injecting formatted numbers ('1,000.5 hours'); unicode lookalike characters from rich-text sources.
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}
- Invalid interval: {0}, expected format P<years>Y<months>M<da
- Invalid unit: {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/5de42d16a6198ca9.
Report an issue: GitHub.