risingwavelabs/risingwave · error

argument of must be boolean, not type

Error message

argument of {} must be boolean, not type {:?}

What it means

Thrown by `enforce_bool_clause` when an expression used in a position that requires a boolean (e.g. the ON condition of a join, a filter, or a CASE/HAVING clause) has a non-boolean return type and is not untyped (untyped expressions are implicitly cast to BOOLEAN instead). The error reports the clause name and the actual return type, so it is essentially a static type check failure during query binding/planning.

Solutions

  1. Add an explicit boolean comparison: change `WHERE flag_col` to `WHERE flag_col = TRUE` (or `<> 0` for integer flags).
  2. For join conditions, use a proper predicate: `JOIN t ON a.id = b.id AND a.enabled`.
  3. Cast once at the source: wrap the expression with `::boolean` or `(expr)::boolean = TRUE` if the underlying type is intentionally convertible.
  4. Fix the UDF/subquery return type to BOOLEAN if the expression author intended a predicate.

Example fix

-- before
SELECT * FROM t JOIN u ON t.id u.id;
-- after
SELECT * FROM t JOIN u ON t.id = u.id;
Defensive patterns

Strategy: validation

Validate before calling

-- check the clause expression type ahead of running the query
-- (in app code) ensure the predicate column is BOOLEAN before composing WHERE clauses
SELECT data_type FROM information_schema.columns
WHERE table_name = 't' AND column_name = 'flag_col';

Try / catch

match enforce_bool_clause(expr, "WHERE") {
    Ok(e) => proceed(e),
    Err(ExprError::BoolCheck(clause, ty)) => {
        // auto-wrap: expr.cast_implicit(DataType::Boolean) or reject query with clear message
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Writing a WHERE/ON/HAVING/CHECK clause whose expression evaluates to a non-boolean type, e.g. `WHERE 1` with a typed integer column expression, `JOIN t ON a.some_int = b.some_int` without comparison, or using a string/UDTF expression directly as a predicate.

Common situations: Porting MySQL-style `WHERE col` truthiness idioms that Postgres/RisingWave rejects; forgetting the comparison operator (`ON a.id b.id`); a UDF or subquery returning INTEGER/TEXT used directly as a filter; accidental operator precedence making the clause a non-boolean expression.

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/a78ec74b3d9b0e16. Report an issue: GitHub.

Appendix: source

Thrown at src/frontend/src/expr/mod.rs:396

            return Err(ErrorCode::BindError(
                "could not determine polymorphic type because input has type unknown".into(),
            ));
        }
        match self.return_type() {
            DataType::Map(m) => Ok(m),
            t => Err(ErrorCode::BindError(format!("expects map but got {t}"))),
        }
    }

    /// Shorthand to enforce implicit cast to boolean
    pub fn enforce_bool_clause(self, clause: &str) -> RwResult<ExprImpl> {
        if self.is_untyped() {
            let inner = self.cast_implicit(&DataType::Boolean)?;
            return Ok(inner);
        }
        let return_type = self.return_type();
        if return_type != DataType::Boolean {
            bail!(
                "argument of {} must be boolean, not type {:?}",
                clause,
                return_type
            )
        }
        Ok(self)
    }

    /// Create "cast" expr to string (`varchar`) type. This is different from a real cast, as
    /// boolean is converted to a single char rather than full word.
    ///
    /// Choose between `cast_output` and `cast_{assign,explicit}(Varchar)` based on `PostgreSQL`'s
    /// behavior on bools. For example, `concat(':', true)` is `:t` but `':' || true` is `:true`.
    /// All other types have the same behavior when formatting to output and casting to string.
    ///
    /// References in `PostgreSQL`:
    /// * [cast](https://github.com/postgres/postgres/blob/a3ff08e0b08dbfeb777ccfa8f13ebaa95d064c04/src/include/catalog/pg_cast.dat#L437-L444)
    /// * [impl](https://github.com/postgres/postgres/blob/27b77ecf9f4d5be211900eda54d8155ada50d696/src/backend/utils/adt/bool.c#L204-L209)

View on GitHub (pinned to 6469eb736d)