risingwavelabs/risingwave · error
Type mismatched between then clause and case
Error message
Type mismatched between then clause and case
What it means
RisingWave's CASE expression builder validates that every THEN clause's return type matches the declared CASE result type. If a WHEN...THEN pair produces a value of a different type than the coalesced output type, building the expression fails. This is an upfront type-consistency check so evaluation never hits a mixed-type array.
Source
Thrown at src/expr/impl/src/scalar/case.rs:352
};
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) {
(BoxedExpression::Sync(when), BoxedExpression::Sync(then)) => {
Ok(WhenClause { when, then })
}View on GitHub (pinned to 6469eb736d)
Solutions
- Cast the offending THEN clause to the CASE result type, e.g. `THEN col::varchar`.
- Check each branch's return type before building and unify them to a common type.
- If you control query construction, ensure the frontend/planner inserts explicit cast expressions so all branches match.
Example fix
// before build_case_expr(return_type, vec![when_expr, then_int_expr]) // then returns INT, return_type is VARCHAR // after let then_expr = then_int_expr.cast(DataType::Varchar)?; build_case_expr(return_type, vec![when_expr, then_expr])
Defensive patterns
Strategy: validation
Validate before calling
fn validate_case_branches(return_type: DataType, branches: &[BoxedExpression]) -> Result<()> {
for then_expr in branches.iter().skip(1).step_by(2) {
if then_expr.return_type() != return_type {
return Err(format!("then type {:?} != case type {:?}", then_expr.return_type(), return_type).into());
}
}
Ok(())
} Type guard
fn is_compatible(e: &BoxedExpression, rt: &DataType) -> bool { e.return_type() == *rt } Prevention
- Cast every THEN branch to the intended common type explicitly.
- Unify branch types at query-writing time instead of relying on implicit coercion.
- Add a pre-build type check for CASE children in code that constructs expressions programmatically.
When it happens
Trigger: Calling build_case_expr with children where a `then` expression's return_type() differs from the computed `return_type` of the CASE expression, e.g. CASE with `THEN 1` branches and an `ELSE 'x'`/varchar-branch that forces the result type to VARCHAR while an INT then-branch remains.
Common situations: Mixing numeric and string branches in CASE; implicit casts not inserted because the frontend planned a different common type; user-defined functions returning unexpected types in one branch.
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
- Expr error: {0}
- Array error: {0}
- Expect Array Type
- Type mismatched between else and case.
- Type mismatched between when clause and condition
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/188181d08142dc3d.
Report an issue: GitHub.