risingwavelabs/risingwave · error · ParserError
ROWS, RANGE, or GROUPS
Error message
ROWS, RANGE, or GROUPS
What it means
This error is raised by `parse_window_frame_units` when the parser cannot recognize the frame unit keyword of a window frame clause (OVER ... ROWS/RANGE/GROUPS/SESSION). The `dispatch!` combinator only accepts ROWS, RANGE, GROUPS or SESSION; anything else fails and `.expect(...)` converts that failure into a user-facing 'expected ROWS, RANGE, or GROUPS' message. It is a SQL syntax error reporting that a window frame unit keyword was required but not found.
Source
Thrown at src/sqlparser/src/parser.rs:914
Ok(Expr::Function(Function {
scalar_as_agg,
name,
arg_list,
within_group,
filter,
over,
}))
}
pub fn parse_window_frame_units(&mut self) -> ModalResult<WindowFrameUnits> {
dispatch! { peek(keyword);
Keyword::ROWS => keyword.value(WindowFrameUnits::Rows),
Keyword::RANGE => keyword.value(WindowFrameUnits::Range),
Keyword::GROUPS => keyword.value(WindowFrameUnits::Groups),
Keyword::SESSION => keyword.value(WindowFrameUnits::Session),
_ => fail,
}
.expect("ROWS, RANGE, or GROUPS")
.parse_next(self)
}
pub fn parse_window_frame(&mut self) -> ModalResult<WindowFrame> {
let units = self.parse_window_frame_units()?;
let bounds = if self.parse_keyword(Keyword::BETWEEN) {
// `BETWEEN <frame_start> AND <frame_end>`
let start = self.parse_window_frame_bound()?;
self.expect_keyword(Keyword::AND)?;
let end = Some(self.parse_window_frame_bound()?);
WindowFrameBounds::Bounds { start, end }
} else if self.parse_keywords(&[Keyword::WITH, Keyword::GAP]) {
// `WITH GAP <gap>`, only for session frames
WindowFrameBounds::Gap(Box::new(self.parse_expr()?))
} else {
// `<frame_start>`
WindowFrameBounds::Bounds {
start: self.parse_window_frame_bound()?,View on GitHub (pinned to 6469eb736d)
Solutions
- Fix the window frame unit keyword to one of ROWS, RANGE, GROUPS (or SESSION in this dialect), e.g. `OVER (ORDER BY x ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)`.
- Ensure the frame clause actually contains a unit keyword before BETWEEN or the bound expression.
- If the query came from another database, rewrite its frame clause to the supported unit keywords.
Example fix
// before SELECT sum(v) OVER (ORDER BY t ROW BETWEEN 1 PRECEDING AND CURRENT ROW) FROM t; // after SELECT sum(v) OVER (ORDER BY t ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) FROM t;
Defensive patterns
Strategy: validation
Validate before calling
const FRAME_UNITS = new Set(['ROWS','RANGE','GROUPS','SESSION']);
function validFrameUnit(unit) { return FRAME_UNITS.has(unit.toUpperCase()); } Type guard
const isFrameUnit = (s) => typeof s === 'string' && ['ROWS','RANGE','GROUPS','SESSION'].includes(s.toUpperCase());
Prevention
- Always write the unit keyword before BETWEEN/UNBOUNDED in a window frame clause.
- Run SQL through the parser in CI before deploying generated queries.
- Map dialect-specific frame keywords before executing.
When it happens
Trigger: Parsing a query with a window frame whose unit token is misspelled, missing, or unsupported, e.g. `OVER (ROWS ...)` missing nothing but written as `OVER (ROW BETWEEN ...)` or `OVER (PARTITION BY x ORDER BY y BETWEEN ...)` where the unit keyword is absent before BETWEEN/UNBOUNDED.
Common situations: Hand-written SQL with typos in window frame clauses; SQL dialects where window frames use different keywords; generated SQL from ORMs or query builders that emit nonstandard frame syntax; porting queries from other engines with exotic frame specs.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/26214308c68e08f2.
Report an issue: GitHub.