risingwavelabs/risingwave · error
for frame bound offset of type `interval`, each field…
Error message
for frame bound offset of type `interval`, each field should be non-negative, but {} is given What it means
For RANGE frames whose offset is an Interval, every field of the interval (months, days, microseconds) must be non-negative. validate in RangeFrameBounds rejects intervals where any component is negative, because mixed-sign intervals make frame comparisons ambiguous.
Solutions
- Use positive interval literals and express direction via PRECEDING/FOLLOWING, e.g. `INTERVAL '1 day' PRECEDING`.
- Normalize computed intervals so all fields are non-negative before building the frame.
- Reject or rewrite such frames in the frontend binder/planner.
Example fix
-- before SELECT sum(x) OVER (ORDER BY ts RANGE BETWEEN INTERVAL '-1 day' PRECEDING AND CURRENT ROW) FROM t; -- after SELECT sum(x) OVER (ORDER BY ts RANGE BETWEEN INTERVAL '1 day' PRECEDING AND CURRENT ROW) FROM t;
Defensive patterns
Strategy: validation
Validate before calling
fn interval_fields_non_negative(i: &Interval) -> bool { i.is_never_negative() } Type guard
fn is_valid_interval_offset(i: Interval) -> bool { i.is_never_negative() } Prevention
- Avoid signed interval literals like '-1 day' in RANGE frames.
- Normalize computed intervals so every field is non-negative.
- Reject mixed-sign intervals in the frontend planner.
When it happens
Trigger: RANGE frame with an Interval offset that is not never-negative, e.g. `RANGE BETWEEN INTERVAL '-1 day' PRECEDING ...` or `INTERVAL '1 month -1 day'`, when validate runs on the constructed bounds.
Common situations: SQL with signed interval literals like `'-1 day'`, or computed interval offsets that can go negative depending on input.
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
- for frame order column of type `timestamptz`, offset should…
- frame bound offset should be non-negative, but
- for session gap of type `interval`, each field should be…
- frame end cannot be UNBOUNDED PRECEDING
- frame start cannot be UNBOUNDED FOLLOWING
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/5808972cf658c23c.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/core/src/window_function/range.rs:118
"frame bound offset should be non-negative, but {} is given",
val
);
}
Ok(())
}
FrameBound::validate_bounds(&self.start, &self.end, |offset| {
match offset.as_scalar_ref_impl() {
// TODO(rc): use decl macro?
ScalarRefImpl::Int16(val) => validate_non_negative(val)?,
ScalarRefImpl::Int32(val) => validate_non_negative(val)?,
ScalarRefImpl::Int64(val) => validate_non_negative(val)?,
ScalarRefImpl::Float32(val) => validate_non_negative(val)?,
ScalarRefImpl::Float64(val) => validate_non_negative(val)?,
ScalarRefImpl::Decimal(val) => validate_non_negative(val)?,
ScalarRefImpl::Interval(val) => {
if !val.is_never_negative() {
bail!(
"for frame bound offset of type `interval`, each field should be non-negative, but {} is given",
val
);
}
if matches!(self.order_data_type, DataType::Timestamptz) {
// for `timestamptz`, we only support offset without `month` and `day` fields
if val.months() != 0 || val.days() != 0 {
bail!(
"for frame order column of type `timestamptz`, offset should not have non-zero `month` and `day`",
);
}
}
}
_ => unreachable!(
"other order column data types are not supported and should be banned in frontend"
),
}
Ok(())View on GitHub (pinned to 6469eb736d)