risingwavelabs/risingwave · error
children expression must not be empty for constant lookup…
Error message
children expression must not be empty for constant lookup expression
What it means
`build_constant_lookup_expr` builds a CASE-like lookup expression whose first child must be the operand compared against constant WHEN keys. With zero children there is no operand, so construction is impossible and the builder rejects it up front.
Solutions
- Ensure the expression always passes at least the operand child; check the planner rewrite that creates constant_lookup.
- Update/fix the frontend rule that collapsed the CASE incorrectly.
- If hand-building expressions, include operand + (when, then)+ pairs.
Defensive patterns
Strategy: validation
Validate before calling
// before building
if children.is_empty() { return Err(anyhow!("constant_lookup requires an operand child")); } Prevention
- Never construct constant_lookup expressions manually.
- Ensure planner rewrites always preserve the operand child.
- Add assertions in code paths that build CASE expressions.
When it happens
Trigger: Invoking the internal `constant_lookup(...)` function (used by the planner for constant-key CASE) with an empty children vector, typically from a planner bug or hand-constructed expression.
Common situations: Frontend/planner mis-optimization producing an empty argument list; custom tooling building expression protobufs manually.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- expect when expression to be const
- 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`
- GenerateSeriesExecutor should not have child!
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/5c81b30154b1455f.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/impl/src/scalar/case.rs:268
impl<E: AsyncExpression> AsyncExpression for ConstantLookupExpression<E> {
async fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {
eval_constant_lookup!(async, self, input)
}
async fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {
let datum = self.operand.eval_row(input).await?;
lookup!(async, self, datum, input)
}
}
#[build_function("constant_lookup(...) -> any", type_infer = "unreachable")]
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() {View on GitHub (pinned to 6469eb736d)