risingwavelabs/risingwave · error
failed to evaluate the input for fallback arm
Error message
failed to evaluate the input for fallback arm
What it means
In the constant-lookup CASE implementation, when a lookup misses all arms the fallback (ELSE) expression is evaluated row-by-row. If that evaluation returns an Err, the macro cannot distinguish expression errors from control flow, so it rethrows this generic wrapper error, discarding the underlying cause.
Source
Thrown at src/expr/impl/src/scalar/case.rs:179
return_type,
arms,
fallback,
operand,
}
}
}
impl<E: ExpressionInfo> ExpressionInfo for ConstantLookupExpression<E> {
fn return_type(&self) -> DataType {
self.return_type.clone()
}
}
macro_rules! eval_fallback_lookup {
($mode:ident, $this:expr, $input:expr) => {{
if let Some(ref fallback) = $this.fallback {
let Ok(res) = risingwave_expr::forward!($mode, fallback, eval_row($input)) else {
bail!("failed to evaluate the input for fallback arm");
};
Ok::<Datum, risingwave_expr::ExprError>(res)
} else {
Ok::<Datum, risingwave_expr::ExprError>(None)
}
}};
}
macro_rules! lookup {
($mode:ident, $this:expr, $datum:expr, $input:expr) => {{
match $datum.as_ref() {
Some(datum) => {
if let Some(expr) = $this.arms.get(datum) {
let Ok(res) = risingwave_expr::forward!($mode, expr, eval_row($input)) else {
bail!("failed to evaluate the input for normal arm");
};
Ok(res)
} else {View on GitHub (pinned to 6469eb736d)
Solutions
- Check the ELSE expression for operations that can fail per-row (casts, division, function domains) and make them total (COALESCE, safe casts).
- Test the else expression standalone on the offending input values.
- If you need the real root cause, run the same expression without the constant-lookup optimization path or check debug logs.
Example fix
// before CASE key WHEN 1 THEN 'a' WHEN 2 THEN 'b' ELSE (val::int / divisor)::text END // after CASE key WHEN 1 THEN 'a' WHEN 2 THEN 'b' ELSE COALESCE((NULLIF(divisor,0) IS NULL, ...)::text, 'n/a') END
Defensive patterns
Strategy: try-catch
Validate before calling
-- make the else arm total before execution -- ensure all casts in ELSE use COALESCE/NULLIF guards
Try / catch
match result {
Err(e) if e.to_string().contains("failed to evaluate the input for fallback arm") => {
// inspect ELSE expression inputs for the offending row
}
other => other?,
} Prevention
- Keep ELSE expressions free of fallible casts and division.
- Guard with COALESCE / NULLIF inside the else arm.
- Test the CASE against edge-case rows before deploying the MV.
When it happens
Trigger: Evaluating a CASE expression built with `build_constant_lookup_expr` where the input datum matches no WHEN constant and the ELSE clause's evaluation fails on that row (e.g. cast overflow, division by zero, domain violation inside the else arm).
Common situations: ELSE clause performing arithmetic on NULL-typed or out-of-domain data; casts inside the else arm failing for particular rows in a materialized view refresh or query.
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
- failed to evaluate the input for normal arm
- failed to lookup and evaluate the expression in `eval`
- Type mismatched between when clause and condition
- missing FORMAT ... ENCODE ...
- missing FORMAT ... ENCODE ...
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/1c75b4b6f258fd71.
Report an issue: GitHub.