risingwavelabs/risingwave · error
session gap should be non-negative, but
Error message
session gap should be non-negative, but {} is given What it means
A session window's gap defines the maximum inactivity distance between rows; a negative gap is meaningless because sessions can only extend forward in time. During frame bounds validation, each gap value (across int16/int32/int64/float32/float64/decimal/interval types) is checked for negativity and rejected.
Solutions
- Use a positive gap value (e.g. INTERVAL '5 seconds')
- If the gap is computed, clamp it: `greatest(gap_expr, 0)`
- Add a frontend/SQL-side check that rejects negative gaps with a friendly message before reaching the executor
Example fix
// before
CREATE ... SESSION('−1 second'::interval)
// after
CREATE ... SESSION('1 second'::interval) Defensive patterns
Strategy: validation
Validate before calling
// SQL-side guard -- reject: gap < 0 -- use: greatest(gap_expr, INTERVAL '0 seconds')
Type guard
fn non_negative_gap(g: ScalarImpl) -> bool { !g.as_scalar_ref_impl().unwrap().is_negative() } Try / catch
match build_session_frame(gap) {
Err(e) if e.to_string().contains("non-negative") => return Err(anyhow!("session gap must be >= 0")),
other => other,
} Prevention
- Wrap user-supplied gaps with greatest(gap, 0)
- Reject negative gaps at SQL parse/planning time
- Never compute the gap from expressions that can go negative without clamping
When it happens
Trigger: Creating a session window frame whose gap literal/expression evaluates to a negative value, e.g. `SESSION('5 seconds'::interval)` with `-'1 second'` or a negative numeric gap, caught during `validate` at plan/exec construction.
Common situations: Typo or sign error in session gap constant; gap derived from a computed expression that can go negative; bad parameterized values bound at runtime.
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 session gap of type `interval`, each field should be…
- for session order column of type `timestamptz`, gap should…
- session frame gap add expression must be sync
- bounded compaction head sequence
- 'copy-on-write' mode is not supported for append-only…
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/7dedb6f7b9c159bc.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/core/src/window_function/session.rs:91
}
impl Display for SessionFrameBounds {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"SESSION WITH GAP {}",
self.gap.as_scalar_ref_impl().to_text()
)
}
}
impl FrameBoundsImpl for SessionFrameBounds {
fn validate(&self) -> Result<()> {
// TODO(rc): maybe can merge with `RangeFrameBounds::validate`
fn validate_non_negative(val: impl IsNegative + Display) -> Result<()> {
if val.is_negative() {
bail!("session gap should be non-negative, but {} is given", val);
}
Ok(())
}
match self.gap.as_scalar_ref_impl() {
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 session gap of type `interval`, each field should be non-negative, but {} is given",
val
);
}View on GitHub (pinned to 6469eb736d)