{"record":{"id":"849238299d67646a","repo":"risingwavelabs/risingwave","slug":"failed-to-evaluate-the-input-for-normal-arm","errorCode":null,"errorMessage":"failed to evaluate the input for normal arm","messagePattern":"failed to evaluate the input for normal arm","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/impl/src/scalar/case.rs","lineNumber":194,"sourceCode":"    ($mode:ident, $this:expr, $input:expr) => {{\n        if let Some(ref fallback) = $this.fallback {\n            let Ok(res) = risingwave_expr::forward!($mode, fallback, eval_row($input)) else {\n                bail!(\"failed to evaluate the input for fallback arm\");\n            };\n            Ok::<Datum, risingwave_expr::ExprError>(res)\n        } else {\n            Ok::<Datum, risingwave_expr::ExprError>(None)\n        }\n    }};\n}\n\nmacro_rules! lookup {\n    ($mode:ident, $this:expr, $datum:expr, $input:expr) => {{\n        match $datum.as_ref() {\n            Some(datum) => {\n                if let Some(expr) = $this.arms.get(datum) {\n                    let Ok(res) = risingwave_expr::forward!($mode, expr, eval_row($input)) else {\n                        bail!(\"failed to evaluate the input for normal arm\");\n                    };\n                    Ok(res)\n                } else {\n                    eval_fallback_lookup!($mode, $this, $input)\n                }\n            }\n            None => eval_fallback_lookup!($mode, $this, $input),\n        }\n    }};\n}\n\nmacro_rules! eval_constant_lookup {\n    ($mode:ident, $this:expr, $input:expr) => {{\n        let input_len = $input.capacity();\n        let mut builder = $this.return_type().create_array_builder(input_len);\n\n        // Evaluate the input DataChunk at first\n        let eval_result = risingwave_expr::forward!($mode, $this.operand, eval($input))?;","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/impl/src/scalar/case.rs#L176-L212","documentation":"In the constant-lookup CASE expression, when the input datum matches a WHEN constant, the corresponding `then` expression is evaluated for the row. If that evaluation fails, the `lookup!` macro bails with this generic message, masking the underlying expression error.","triggerScenarios":"Evaluating a CASE with constant WHEN keys where the matched THEN arm's expression errors on a specific row (overflow, failed cast, function domain error inside the then expression).","commonSituations":"THEN arms containing casts or arithmetic that fail on particular rows; data arriving in a materialized view refresh that violates assumptions of the then expression.","solutions":["Harden the THEN expressions: wrap risky casts/arithmetic in COALESCE or CASE guards.","Identify the offending rows by evaluating each then expression independently.","Add explicit type handling so the then expression is total over the input domain."],"exampleFix":"// before\nCASE status WHEN 1 THEN (raw::int * 100)::text ELSE 'other' END\n// after\nCASE status WHEN 1 THEN COALESCE((raw::int * 100)::text, 'invalid') ELSE 'other' END","handlingStrategy":"try-catch","validationCode":"-- harden THEN arms before execution:\n-- THEN COALESCE((x::int)::text, 'default')","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"failed to evaluate the input for normal arm\") => {\n        // find the matched arm and its failing row input\n    }\n    other => other?,\n}","preventionTips":["Make every THEN expression total over the input domain.","Avoid raw casts in THEN arms; validate data upstream.","Sanitize or filter rows that can violate cast assumptions."],"tags":["rust","sql","case-expression","error-wrapping"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}