risingwavelabs/risingwave · error
expect when expression to be const
Error message
expect when expression to be const
What it means
The constant-lookup optimization requires each WHEN key to be a constant that can be evaluated at build time so it can be stored in a HashMap. If `eval_const` on a WHEN expression fails or returns NULL, the builder cannot build the lookup table and bails.
Solutions
- Ensure WHEN keys are literal constants in the query.
- Check whether the planner incorrectly converted a general CASE to constant_lookup; report/fix the frontend rule.
- Use the general `build_case_expr` path instead for non-constant WHEN conditions.
Example fix
// before (non-const WHEN key) CASE x WHEN some_column THEN 'a' ELSE 'b' END // after CASE x WHEN 1 THEN 'a' WHEN 2 THEN 'b' ELSE 'b' END
Defensive patterns
Strategy: validation
Validate before calling
// ensure WHEN is constant before routing to constant lookup
let is_const = matches!(when_expr, Expr::Literal(_) | Expr::InputRef(_)) && when_expr.eval_const().is_ok();
if !is_const { /* use general case builder */ } Prevention
- Only route CASEs with literal WHEN keys to constant lookup.
- Check eval_const returns Some (not NULL) for each key.
- Keep WHEN keys deterministic and literal in SQL.
When it happens
Trigger: `build_constant_lookup_expr` receiving a WHEN expression that is not a literal/stable constant (e.g. a column reference, non-deterministic function) or evaluates to NULL, usually from a planner rule that misjudged const-ness.
Common situations: CASE with non-literal WHEN conditions reaching this builder; planner version differences changing which CASEs are routed to constant lookup.
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
- children expression must not be empty for constant lookup…
- failed to evaluate the input for fallback arm
- failed to evaluate the input for normal arm
- failed to lookup and evaluate the expression in `eval`
- Type mismatched between else and case.
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/32c426ab0a8f6154.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/impl/src/scalar/case.rs:281
fn build_constant_lookup_expr(
return_type: DataType,
children: Vec<BoxedExpression>,
) -> Result<BoxedExpression> {
if children.is_empty() {
bail!("children expression must not be empty for constant lookup expression");
}
let mut children = children;
let operand = children.remove(0);
let mut arms = HashMap::new();
// Build the `arms` with iterating over `when` & `then` clauses
let mut iter = children.into_iter().array_chunks();
for [when, then] in iter.by_ref() {
let Ok(Some(s)) = when.eval_const() else {
bail!("expect when expression to be const");
};
arms.insert(s, then);
}
let fallback = if let Some(else_clause) = iter.into_remainder().next() {
if else_clause.return_type() != return_type {
bail!("Type mismatched between else and case.");
}
Some(else_clause)
} else {
None
};
let BoxedExpression::Sync(operand) = operand else {
return Ok(ConstantLookupExpression::new(return_type, arms, fallback, operand).boxed());
};
let arms: Vec<_> = arms.into_iter().collect();
let sync_arms: HashMap<ScalarImpl, Arc<dyn SyncExpression>> = match try_convert_all(View on GitHub (pinned to 6469eb736d)