risingwavelabs/risingwave · error

range frame offset add expression must be sync

Error message

range frame offset add expression must be sync

What it means

When preparing a RangeFrameBounds, the generated add (and subtract) expression between the order column and offset is built via build_func; the result must be a synchronous (non-async/non-table) expression for the frame calculation to work inline. If build_func returns anything else, from_protobuf fails with this invariant error.

Solutions

  1. Use a supported order column type for RANGE frames (integer, numeric, date/timestamp, or compatible interval) so Add/Subtract build as sync expressions.
  2. Add a sync expression implementation for the missing type combination in the expression crate.
  3. Check recent expression-framework changes if this previously worked (BoxedExpression::Sync variant coverage).

Example fix

// ensure build_func result is sync for the type pair, or add an impl:
// before: Add on timestamptz + interval-with-months falls to unsupported variant
// after: restrict offset to microsecond-only intervals so Add maps to BoxedExpression::Sync
Defensive patterns

Strategy: try-catch

Try / catch

let add_expr = match build_func(PbExprType::Add, order_type.clone(), vec![input.boxed(), offset.boxed()]) {
    Ok(crate::expr::BoxedExpression::Sync(e)) => e,
    Ok(_) | Err(e2) => return Err(anyhow!("unsupported RANGE frame types (order/offset): {:?}", e2.map(|e| e.to_string()))),
};

Prevention

When it happens

Trigger: Deserializing a RANGE frame where PbExprType::Add (or Subtract) over the order/offset data types builds into a non-sync expression — typically an unsupported type combination that maps to an async or missing expression implementation.

Common situations: Exotic order-column/offset type pairs (e.g. certain decimal/interval/timestamptz combos) where the arithmetic expression engine has no sync implementation; expression framework refactors changing BoxedExpression variants.

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/26f42e62664a57ae. Report an issue: GitHub.

Appendix: source

Thrown at src/expr/core/src/window_function/range.rs:341

            offset,
            add_expr: None,
            sub_expr: None,
        }
    }

    fn prepare(&mut self, order_data_type: &DataType, offset_data_type: &DataType) -> Result<()> {
        use risingwave_pb::expr::expr_node::PbType as PbExprType;

        let input_expr = InputRefExpression::new(order_data_type.clone(), 0);
        let offset_expr =
            LiteralExpression::new(offset_data_type.clone(), Some(self.offset.clone()));
        let add_expr = build_func(
            PbExprType::Add,
            order_data_type.clone(),
            vec![input_expr.clone().boxed(), offset_expr.clone().boxed()],
        )?;
        let crate::expr::BoxedExpression::Sync(add_expr) = add_expr else {
            bail!("range frame offset add expression must be sync");
        };
        self.add_expr = Some(add_expr);

        let sub_expr = build_func(
            PbExprType::Subtract,
            order_data_type.clone(),
            vec![input_expr.boxed(), offset_expr.boxed()],
        )?;
        let crate::expr::BoxedExpression::Sync(sub_expr) = sub_expr else {
            bail!("range frame offset subtract expression must be sync");
        };
        self.sub_expr = Some(sub_expr);
        Ok(())
    }

    pub fn new_for_test(
        offset: ScalarImpl,
        order_data_type: &DataType,

View on GitHub (pinned to 6469eb736d)