{"record":{"id":"5c81b30154b1455f","repo":"risingwavelabs/risingwave","slug":"children-expression-must-not-be-empty-for-constant","errorCode":null,"errorMessage":"children expression must not be empty for constant lookup expression","messagePattern":"children expression must not be empty for constant lookup expression","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/impl/src/scalar/case.rs","lineNumber":268,"sourceCode":"\nimpl<E: AsyncExpression> AsyncExpression for ConstantLookupExpression<E> {\n    async fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {\n        eval_constant_lookup!(async, self, input)\n    }\n\n    async fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {\n        let datum = self.operand.eval_row(input).await?;\n        lookup!(async, self, datum, input)\n    }\n}\n\n#[build_function(\"constant_lookup(...) -> any\", type_infer = \"unreachable\")]\nfn build_constant_lookup_expr(\n    return_type: DataType,\n    children: Vec<BoxedExpression>,\n) -> Result<BoxedExpression> {\n    if children.is_empty() {\n        bail!(\"children expression must not be empty for constant lookup expression\");\n    }\n\n    let mut children = children;\n\n    let operand = children.remove(0);\n\n    let mut arms = HashMap::new();\n\n    // Build the `arms` with iterating over `when` & `then` clauses\n    let mut iter = children.into_iter().array_chunks();\n    for [when, then] in iter.by_ref() {\n        let Ok(Some(s)) = when.eval_const() else {\n            bail!(\"expect when expression to be const\");\n        };\n        arms.insert(s, then);\n    }\n\n    let fallback = if let Some(else_clause) = iter.into_remainder().next() {","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/impl/src/scalar/case.rs#L250-L286","documentation":"`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.","triggerScenarios":"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.","commonSituations":"Frontend/planner mis-optimization producing an empty argument list; custom tooling building expression protobufs manually.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before building\nif children.is_empty() { return Err(anyhow!(\"constant_lookup requires an operand child\")); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never construct constant_lookup expressions manually.","Ensure planner rewrites always preserve the operand child.","Add assertions in code paths that build CASE expressions."],"tags":["rust","expression-builder","case-expression","planner"],"backgroundTag":"missing-required-argument","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"}