risingwavelabs/risingwave · error
session frame gap add expression must be sync
Error message
session frame gap add expression must be sync
What it means
Session frame construction builds an Add expression (`order_col + gap`) used to compute the session end per row. Like the RANGE frame path, the session executor only supports synchronous expressions, so the built Add must be the `BoxedExpression::Sync` variant; otherwise construction fails.
Solutions
- Ensure the Add expression implementation for the order column type builds a Sync variant
- Check `build_func` dispatch for the affected type and add a sync constructor if missing
- Align frontend and backend versions
Example fix
// before: non-sync Add built by builder
let add_expr = build_func(PbExprType::Add, order_data_type, vec![input_expr.boxed(), gap_expr.boxed()])?;
// after: guarantee Sync variant from the constructor
let crate::expr::BoxedExpression::Sync(add_expr) = add_expr else {
bail!("session frame gap add expression must be sync");
}; Defensive patterns
Strategy: try-catch
Validate before calling
fn ensure_add_sync(e: &BoxedExpression) -> Result<()> {
if !matches!(e, BoxedExpression::Sync(_)) { bail!("session add expr not sync"); }
Ok(())
} Type guard
fn is_sync(e: &BoxedExpression) -> bool { matches!(e, BoxedExpression::Sync(_)) } Try / catch
match SessionFrameBounds::from_protobuf(&pb) {
Err(e) if e.to_string().contains("must be sync") => report_or_fallback(e),
other => other,
} Prevention
- Ensure Add for all order-column types builds Sync expressions
- Add compile-time/test coverage per data type
- Keep frontend/backend versions aligned
When it happens
Trigger: `SessionFrameBounds::prepare` during `from_protobuf` where the Add expression over the order column and gap compiles to a non-sync (e.g. async) expression variant.
Common situations: New data types or expression kinds lacking a sync eval implementation; frontend/backend version mismatch so the builder wraps Add in an unexpected variant.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- for session gap of type `interval`, each field should be…
- for session order column of type `timestamptz`, gap should…
- range frame offset subtract expression must be sync
- session gap should be non-negative, but
- offset of `RowsFrameBound` must be `Integer`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/20c4900d6c8108cb.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/core/src/window_function/session.rs:172
pub fn new(gap: ScalarImpl) -> Self {
Self {
gap,
add_expr: None,
}
}
fn prepare(&mut self, order_data_type: &DataType, gap_data_type: &DataType) -> Result<()> {
use risingwave_pb::expr::expr_node::PbType as PbExprType;
let input_expr = InputRefExpression::new(order_data_type.clone(), 0);
let gap_expr = LiteralExpression::new(gap_data_type.clone(), Some(self.gap.clone()));
let add_expr = build_func(
PbExprType::Add,
order_data_type.clone(),
vec![input_expr.boxed(), gap_expr.boxed()],
)?;
let crate::expr::BoxedExpression::Sync(add_expr) = add_expr else {
bail!("session frame gap add expression must be sync");
};
self.add_expr = Some(add_expr);
Ok(())
}
pub fn new_for_test(
gap: ScalarImpl,
order_data_type: &DataType,
gap_data_type: &DataType,
) -> Self {
let mut gap = Self::new(gap);
gap.prepare(order_data_type, gap_data_type).unwrap();
gap
}
fn for_calc(&self) -> SessionFrameGapRef<'_> {
SessionFrameGapRef {
add_expr: self.add_expr.as_ref().unwrap().as_ref(),View on GitHub (pinned to 6469eb736d)