risingwavelabs/risingwave · error

Type mismatched between when clause and condition

Error message

Type mismatched between when clause and condition

What it means

In `build_case_expr`, every WHEN condition expression must return BOOLEAN, since CASE conditions are logically evaluated as predicates. A non-boolean WHEN type means the query plan is malformed, so the builder rejects it.

Source

Thrown at src/expr/impl/src/scalar/case.rs:349

            .boxed());
        }
        None => None,
    };
    Ok(ConstantLookupExpression::new(return_type, sync_arms, fallback, operand).boxed())
}

#[build_function("case(...) -> any", type_infer = "unreachable")]
fn build_case_expr(
    return_type: DataType,
    children: Vec<BoxedExpression>,
) -> Result<BoxedExpression> {
    // children: (when, then)+, (else_clause)?
    let len = children.len();
    let mut when_clauses = Vec::with_capacity(len / 2);
    let mut iter = children.into_iter().array_chunks();
    for [when, then] in iter.by_ref() {
        if when.return_type() != DataType::Boolean {
            bail!("Type mismatched between when clause and condition");
        }
        if then.return_type() != return_type {
            bail!("Type mismatched between then clause and case");
        }
        when_clauses.push(WhenClause { when, then });
    }
    let else_clause = 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 sync_when_clauses = match try_convert_all(
        when_clauses,
        |WhenClause { when, then }| match (when, then) {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Wrap the condition in an explicit comparison: `CASE WHEN col = 1 THEN ...` instead of `CASE WHEN col THEN ...`.
  2. Add an explicit cast/comparison so the condition is boolean.
  3. Verify the frontend type coercion rules for searched CASE conditions.

Example fix

// before
CASE WHEN status THEN 'active' ELSE 'inactive' END  -- status is int
// after
CASE WHEN status = 1 THEN 'active' ELSE 'inactive' END
Defensive patterns

Strategy: validation

Validate before calling

-- ensure condition is boolean before CASE
CASE WHEN status = 1 THEN ... -- not CASE WHEN status THEN ...
-- app-side guard:
if (whenExpr.returnType !== 'boolean') wrapInComparison(whenExpr);

Prevention

When it happens

Trigger: `build_case_expr` receiving a (when, then) pair whose `when` expression's return type is not `DataType::Boolean` — e.g. an integer used directly as a condition without an explicit comparison, or a planner that failed to insert a boolean cast.

Common situations: Porting SQL that relies on non-standard truthy semantics (e.g. `CASE x WHEN 1 THEN ...` translated incorrectly to searched CASE); frontend type inference bugs; schema changes turning a boolean column into int.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/2c162baf579fffcb. Report an issue: GitHub.