risingwavelabs/risingwave · error

dynamic filter condition eval must return bool array

Error message

dynamic filter condition eval must return bool array

What it means

This is an internal invariant panic in the DynamicFilter executor. After evaluating the dynamic filter condition expression over a chunk via `eval_infallible`, the code expects the result to be a Bool array (one boolean per row). If the expression evaluator returned any other array type (Int32, Utf8, etc.), the executor cannot compute row visibility and panics. It should never happen for a correctly planned dynamic filter, since the frontend always builds the condition as a boolean expression.

Source

Thrown at src/stream/src/executor/dynamic_filter.rs:118

            Some(cond.eval_infallible(chunk).await)
        } else {
            None
        };

        let below_watermark = if let Some(cond) = below_watermark_condition {
            Some(cond.eval_infallible(chunk).await)
        } else {
            None
        };

        for (idx, (op, row)) in chunk.rows().enumerate() {
            let left_val = row.datum_at(self.key_l).to_owned_datum();

            let satisfied_dyn_filter_cond = if let Some(array) = &filter_results {
                if let ArrayImpl::Bool(results) = &**array {
                    results.value_at(idx).unwrap_or(false)
                } else {
                    panic!("dynamic filter condition eval must return bool array")
                }
            } else {
                // A NULL right value implies a false evaluation for all rows
                false
            };
            let below_watermark = if let Some(array) = &below_watermark {
                if let ArrayImpl::Bool(results) = &**array {
                    results.value_at(idx).unwrap_or(false)
                } else {
                    panic!("below watermark check condition eval must return bool array")
                }
            } else {
                // there was no state cleaning watermark before
                false
            };

            match op {
                Op::Insert | Op::Delete => {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check how the dynamic filter condition is built in the frontend planner and ensure the expression's return type is Boolean (literal_type checked as boolean).
  2. Inspect the comparator/condition construction (PbExprNodeType dispatch) for changes that could yield a non-bool expression result.
  3. Capture the chunk and the expression's return_type at the panic site and file an issue with the plan; wrap executor polling in the stream catch mechanism if resilience is needed.

Example fix

// before
let satisfied = if let ArrayImpl::Bool(results) = &**array { results.value_at(idx).unwrap_or(false) } else { panic!("...") };
// after
let satisfied = match &**array {
    ArrayImpl::Bool(results) => results.value_at(idx).unwrap_or(false),
    other => return Err(StreamExecutorError::internal(anyhow::anyhow!(
        "dynamic filter condition eval returned {:?}, expected Bool array", other.data_type()
    ))),
};
Defensive patterns

Strategy: type-guard

Validate before calling

// Before relying on eval results:
let array = filter_results.as_ref().expect("condition present");
assert!(matches!(&**array, ArrayImpl::Bool(_)), "filter cond must eval to Bool array");

Type guard

fn is_bool_array(a: &ArrayImpl) -> bool { matches!(a, ArrayImpl::Bool(_)) }

Try / catch

// In RisingWave stream executors panics abort the actor; guard at plan time instead:
match &**array {
    ArrayImpl::Bool(b) => b.value_at(idx).unwrap_or(false),
    other => return Err(StreamExecutorError::internal(anyhow::anyhow!("expected Bool array, got {:?}", other.data_type()))),
}

Prevention

When it happens

Trigger: apply_batch is called (from execute_inner) with a Some(filter_condition) whose NonStrictExpression evaluates (via eval_infallible on the StreamChunk) to an ArrayImpl that is not ArrayImpl::Bool. This would require the planner/expr dispatcher to produce a non-boolean return type for the dynamic filter predicate.

Common situations: Practically only hit by RisingWave developers changing the dynamic-filter planning code, the expression type inference, or adding new expression node types that break the boolean return-type contract of the generated filter condition; end users cannot trigger it via SQL.

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


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