{"record":{"id":"fbfd864e7063b535","repo":"risingwavelabs/risingwave","slug":"for-session-gap-of-type-interval-each-field-sho","errorCode":null,"errorMessage":"for session gap of type `interval`, each field should be non-negative, but {} is given","messagePattern":"for session gap of type `interval`, each field should be non-negative, but (.+?) is given","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/core/src/window_function/session.rs","lineNumber":105,"sourceCode":"        // TODO(rc): maybe can merge with `RangeFrameBounds::validate`\n\n        fn validate_non_negative(val: impl IsNegative + Display) -> Result<()> {\n            if val.is_negative() {\n                bail!(\"session gap should be non-negative, but {} is given\", val);\n            }\n            Ok(())\n        }\n\n        match self.gap.as_scalar_ref_impl() {\n            ScalarRefImpl::Int16(val) => validate_non_negative(val)?,\n            ScalarRefImpl::Int32(val) => validate_non_negative(val)?,\n            ScalarRefImpl::Int64(val) => validate_non_negative(val)?,\n            ScalarRefImpl::Float32(val) => validate_non_negative(val)?,\n            ScalarRefImpl::Float64(val) => validate_non_negative(val)?,\n            ScalarRefImpl::Decimal(val) => validate_non_negative(val)?,\n            ScalarRefImpl::Interval(val) => {\n                if !val.is_never_negative() {\n                    bail!(\n                        \"for session gap of type `interval`, each field should be non-negative, but {} is given\",\n                        val\n                    );\n                }\n                if matches!(self.order_data_type, DataType::Timestamptz) {\n                    // for `timestamptz`, we only support gap without `month` and `day` fields\n                    if val.months() != 0 || val.days() != 0 {\n                        bail!(\n                            \"for session order column of type `timestamptz`, gap should not have non-zero `month` and `day`\",\n                        );\n                    }\n                }\n            }\n            _ => unreachable!(\n                \"other order column data types are not supported and should be banned in frontend\"\n            ),\n        }\n        Ok(())","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/core/src/window_function/session.rs#L87-L123","documentation":"For interval-typed session gaps, a simple sign check is insufficient because an Interval has months/days/microseconds fields. Validation uses `is_never_negative()`, requiring every field of the interval to be non-negative (e.g. '1 month -1 day' is rejected even if the total duration is positive).","triggerScenarios":"Session window with an interval gap where any component field is negative, e.g. `INTERVAL '1 month -1 day'` or `INTERVAL '-5 seconds'`, detected in `validate` (via `is_canonical`).","commonSituations":"Arithmetic on intervals producing mixed-sign components; users assuming total-duration semantics instead of per-field semantics.","solutions":["Rewrite the gap so all interval fields are non-negative (e.g. INTERVAL '1 month 1 day')","Normalize the interval before passing it (split/abs each field)","Clamp negative fields to zero in the expression producing the gap"],"exampleFix":"// before\nSESSION(INTERVAL '1 month -1 day')\n// after\nSESSION(INTERVAL '1 month 1 day')","handlingStrategy":"validation","validationCode":"fn interval_never_negative(i: Interval) -> bool { i.is_never_negative() }","typeGuard":"fn safe_interval_gap(i: Interval) -> bool { i.months() >= 0 && i.days() >= 0 && i.useconds() >= 0 }","tryCatchPattern":"if !gap.is_never_negative() {\n    return Err(anyhow!(\"each interval field of the session gap must be non-negative\"));\n}","preventionTips":["Avoid interval arithmetic that mixes signs across fields","Normalize/justify intervals before use as gaps","Document per-field non-negativity for users"],"tags":["rust","window-function","session-window","interval"],"backgroundTag":"invalid-argument-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}