risingwavelabs/risingwave · error

MATCH_RECOGNIZE WITHIN span predicate has type {}, expected

Error message

MATCH_RECOGNIZE WITHIN span predicate has type {}, expected boolean

What it means

The `within` field must be a boolean span predicate evaluated per candidate row. The decoder found a non-boolean expression type and rejects the plan, since a non-boolean predicate cannot drive the span window logic.

Source

Thrown at src/stream/src/from_proto/match_recognize.rs:204

                    order_key_indices[0],
                    input.schema().len()
                )
            })?;
        if let Some(deadline) = &within_deadline
            && deadline.return_type() != order_key_type
        {
            return Err(anyhow::anyhow!(
                "MATCH_RECOGNIZE WITHIN deadline has type {} but the ORDER BY column has type {}; \
                 the two are compared directly",
                deadline.return_type(),
                order_key_type,
            )
            .into());
        }
        if let Some(predicate) = &within
            && predicate.return_type() != DataType::Boolean
        {
            return Err(anyhow::anyhow!(
                "MATCH_RECOGNIZE WITHIN span predicate has type {}, expected boolean",
                predicate.return_type(),
            )
            .into());
        }

        let vnode_bitmap = params.vnode_bitmap.clone().map(std::sync::Arc::new);
        let state_table_catalog = node
            .state_table
            .as_ref()
            .ok_or_else(|| anyhow::anyhow!("MATCH_RECOGNIZE node missing its state table"))?;
        let state_table =
            StateTableBuilder::new(state_table_catalog, store.clone(), vnode_bitmap.clone())
                .forbid_preload_all_rows()
                .build()
                .await;
        let exec = MatchRecognizeExecutor::new(MatchRecognizeExecutorArgs {
            ctx: params.actor_context,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Ensure the WITHIN expression is a boolean condition, e.g. `WITHIN (ts > now() - INTERVAL '1 hour')` rather than a bare column.
  2. Re-create the streaming job so the current binder regenerates the predicate.
  3. Align node versions to rule out version skew.
  4. If the SQL predicate is clearly boolean yet fails, report a binder bug.

Example fix

-- before
MATCH_RECOGNIZE ( ORDER BY ts WITHIN ts ... )
-- after
MATCH_RECOGNIZE ( ORDER BY ts WITHIN ts >= now() - INTERVAL '1 hour' ... )
Defensive patterns

Strategy: validation

Validate before calling

// SQL-level guard: WITHIN must be a boolean expression
-- write WITHIN (<boolean condition>), e.g. WITHIN (ts >= now() - INTERVAL '1 hour')

Try / catch

// Pre-check decoded predicate type
if let Some(p) = &within && p.return_type() != DataType::Boolean {
    return Err(anyhow!("WITHIN predicate must be boolean, got {}", p.return_type()));
}

Prevention

When it happens

Trigger: `new_boxed_executor` decodes a MatchRecognizeNode whose `within` expression's `return_type()` is not `DataType::Boolean` — e.g. the binder produced a raw column or arithmetic expression instead of a comparison.

Common situations: Writing `WITHIN <expr>` where `<expr>` is not a boolean condition (e.g. a column or numeric literal); frontend/binder bugs failing to wrap the expression in a comparison; version skew changing expression typing.

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