risingwavelabs/risingwave · error
for session order column of type `timestamptz`, gap should…
Error message
for session order column of type `timestamptz`, gap should not have non-zero `month` and `day`
What it means
Session windows ordered by `timestamptz` only support gaps whose duration is expressible as exact microseconds — months and days have ambiguous, timezone/DST-dependent lengths. Therefore a gap for a timestamptz order column must have zero `months` and zero `days` fields.
Solutions
- Express the gap in hours/minutes/seconds/microseconds, e.g. INTERVAL '30 days' -> INTERVAL '720 hours'
- Change the order column type to TIMESTAMP if day/month granularity is truly needed
- Catch this at the frontend and emit a user-friendly hint
Example fix
// before OVER (ORDER BY ts_tz SESSION(INTERVAL '1 month')) // after OVER (ORDER BY ts_tz SESSION(INTERVAL '720 hours'))
Defensive patterns
Strategy: validation
Validate before calling
fn timestamptz_safe_gap(i: Interval) -> bool { i.months() == 0 && i.days() == 0 } Try / catch
if order_type == DataType::Timestamptz && (gap.months() != 0 || gap.days() != 0) {
return Err(anyhow!("convert month/day gap to hours for timestamptz order columns"));
} Prevention
- Express timestamptz session gaps only in hours/minutes/seconds/microseconds
- Use TIMESTAMP order columns if month/day gaps are required
- Add a planner-level check with a helpful hint
When it happens
Trigger: Session window whose order column is TIMESTAMPTZ and gap interval has non-zero months or days, e.g. `SESSION(INTERVAL '1 month')` over a timestamptz order key, caught in `validate` via `is_canonical`.
Common situations: Copy-pasting a session definition from a TIMESTAMP-column query to a TIMESTAMPTZ one; choosing '1 month'/'1 day' gaps intuitively without realizing the timestamptz restriction.
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…
- session frame gap add expression must be sync
- session gap should be non-negative, but
- for frame order column of type `timestamptz`, offset should…
- offset of `RowsFrameBound` must be `Integer`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/dca488c3a313b066.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/core/src/window_function/session.rs:113
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
);
}
if matches!(self.order_data_type, DataType::Timestamptz) {
// for `timestamptz`, we only support gap without `month` and `day` fields
if val.months() != 0 || val.days() != 0 {
bail!(
"for session order column of type `timestamptz`, gap should not have non-zero `month` and `day`",
);
}
}
}
_ => unreachable!(
"other order column data types are not supported and should be banned in frontend"
),
}
Ok(())
}
}
impl SessionFrameBounds {
pub fn minimal_next_start_of(&self, end_order_value: impl ToOwnedDatum) -> Datum {
self.gap.for_calc().minimal_next_start_of(end_order_value)
}
}View on GitHub (pinned to 6469eb736d)