risingwavelabs/risingwave · error
frame starting from current row cannot have preceding rows
Error message
frame starting from current row cannot have preceding rows
What it means
During window frame bound validation, a frame starting at CURRENT ROW is not allowed to end at a Preceding row, since the end would be before the start. validate_bounds rejects this contradictory frame specification.
Source
Thrown at src/expr/core/src/window_function/call.rs:227
Preceding(offset) | Following(offset) => Some(offset),
}
}
pub(super) fn validate_bounds(
start: &Self,
end: &Self,
offset_checker: impl Fn(&T) -> Result<()>,
) -> Result<()> {
match (start, end) {
(_, UnboundedPreceding) => bail!("frame end cannot be UNBOUNDED PRECEDING"),
(UnboundedFollowing, _) => {
bail!("frame start cannot be UNBOUNDED FOLLOWING")
}
(Following(_), CurrentRow) | (Following(_), Preceding(_)) => {
bail!("frame starting from following row cannot have preceding rows")
}
(CurrentRow, Preceding(_)) => {
bail!("frame starting from current row cannot have preceding rows")
}
_ => {}
}
for bound in [start, end] {
if let Some(offset) = bound.offset_value() {
offset_checker(offset)?;
}
}
Ok(())
}
pub fn map<U>(self, f: impl Fn(T) -> U) -> FrameBound<U> {
match self {
UnboundedPreceding => UnboundedPreceding,
Preceding(offset) => Preceding(f(offset)),
CurrentRow => CurrentRow,View on GitHub (pinned to 6469eb736d)
Solutions
- Rewrite the frame as `BETWEEN n PRECEDING AND CURRENT ROW` to scan backwards.
- Use `BETWEEN CURRENT ROW AND n FOLLOWING` if forward-looking rows were intended.
- Verify planner/frontend code that emits PbFrameBound pairs does not reverse start/end.
Example fix
-- before SELECT sum(x) OVER (ORDER BY ts ROWS BETWEEN CURRENT ROW AND 3 PRECEDING) FROM t; -- after SELECT sum(x) OVER (ORDER BY ts ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) FROM t;
Defensive patterns
Strategy: validation
Validate before calling
fn frame_bounds_valid(start: &Bound, end: &Bound) -> bool {
!matches!((start, end), (Bound::CurrentRow, Bound::Preceding(_)))
} Type guard
fn is_current_row_start(b: &Bound) -> bool { matches!(b, Bound::CurrentRow) } Prevention
- Normalize reversed frames to PRECEDING..CURRENT ROW form at parse time.
- Document that frame start must not be after frame end.
- Add frontend binder checks before building the protobuf plan.
When it happens
Trigger: Constructing a WindowFuncCall with frame bounds start=CurrentRow and end=Preceding(n), e.g. SQL `ROWS BETWEEN CURRENT ROW AND 3 PRECEDING`.
Common situations: User SQL with reversed frame direction (author intended FOLLOWING), or programmatic frame construction that mixes up preceding/following semantics.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- frame end cannot be UNBOUNDED PRECEDING
- frame start cannot be UNBOUNDED FOLLOWING
- frame starting from following row cannot have preceding rows
- Invalid order key: empty item in `{expr}`
- Invalid order key item `{item}`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/380503b1d6ffd567.
Report an issue: GitHub.