risingwavelabs/risingwave · error · ParserError

date/time field

Error message

date/time field

What it means

A panic message (via `.expect`) in the EXTRACT expression parser: the token after `EXTRACT` could not be read as a date/time field word or quoted string. It means the parser reached the field position but `verify_map` returned None, violating an internal assumption that a field token was present after the `cut_err` lookahead.

Solutions

  1. Provide a valid field name: `EXTRACT(YEAR FROM ts)` or `EXTRACT('year' FROM ts)`.
  2. If you maintain the parser, replace `.expect` with a `cut_err`/context parse failure so it becomes a user-facing syntax error rather than a panic.
  3. Validate SQL before submitting (lint with a parser that reports the missing field).

Example fix

// before
EXTRACT(123 FROM ts)
// after
EXTRACT(YEAR FROM ts)
Defensive patterns

Strategy: validation

Validate before calling

const FIELDS: [&str; 14] = ["YEAR","MONTH","DAY","HOUR","MINUTE","SECOND","DOY","DOW","EPOCH","WEEK","QUARTER","DECADE","CENTURY","MILLENNIUM"];
fn valid_extract_field(f: &str) -> bool { FIELDS.contains(&f.to_uppercase().as_str()) }

Try / catch

// Panics, not Result: catch by validating SQL before parse, or wrap
let result = std::panic::catch_unwind(|| parse_extract(sql));
if result.is_err() { /* report invalid EXTRACT field */ }

Prevention

When it happens

Trigger: Parsing `EXTRACT(` where the next token is not a Word or single-quoted string (e.g. `EXTRACT(123 FROM ts)` or `EXTRACT()`) — the `expect` panics instead of producing a normal parse error.

Common situations: Malformed SQL like `EXTRACT()` or `EXTRACT(1 FROM col)`; programmatic SQL generation with missing field; user typo placing a paren or number where the field name belongs.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/de5c9f6961859e3c. Report an issue: GitHub.

Appendix: source

Thrown at src/sqlparser/src/parser_v2/expr.rs:118

        data_type: data_type,
        _: Token::RParen,
    }});

    trace("expr_try_cast", parse).parse_next(input)
}

/// Consume a SQL EXTRACT function e.g. `EXTRACT(YEAR FROM expr)`
pub fn expr_extract<S>(input: &mut S) -> ModalResult<Expr>
where
    S: TokenStream,
{
    let mut date_time_field = token
        .verify_map(|token| match token.token {
            Token::Word(w) => Some(w.value.to_uppercase()),
            Token::SingleQuotedString(s) => Some(s.to_uppercase()),
            _ => None,
        })
        .expect("date/time field");

    let parse = cut_err(seq! {Expr::Extract {
        _: Token::LParen,
        field: date_time_field,
        _: Keyword::FROM,
        expr: expr_parse.map(Box::new),
        _: Token::RParen,
    }});

    trace("expr_extract", parse).parse_next(input)
}

/// Consume `SUBSTRING (EXPR [FROM 1] [FOR 3])`
pub fn expr_substring<S>(input: &mut S) -> ModalResult<Expr>
where
    S: TokenStream,
{
    let mut substring_from = opt(preceded(

View on GitHub (pinned to 6469eb736d)