risingwavelabs/risingwave · error

`DynamicFilterExecutor` only supports comparators…

Error message

`DynamicFilterExecutor` only supports comparators: GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual

What it means

The DynamicFilter executor proto-to-executor conversion only supports the four ordering comparators (>, >=, <, <=). If the condition's function type is anything else (e.g. equal or non-comparison functions), `new_boxed_executor` bails, since dynamic filtering is only defined for range comparisons.

Solutions

  1. Fix the frontend so only ordering comparators are planned as dynamic filters.
  2. Rewrite the query so the predicate uses >, >=, <, or <= against the filter column.
  3. Upgrade stream/frontend components together so comparator support matches.
Defensive patterns

Strategy: validation

Validate before calling

// before constructing the node
let ok = matches!(comparator, GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual);
if !ok { /* plan it as a regular filter instead of a dynamic filter */ }

Type guard

fn is_supported_comparator(c: ExprType) -> bool {
    matches!(c, GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual)
}

Prevention

When it happens

Trigger: Building a `DynamicFilterExecutor` from a proto node whose condition function type is not GreaterThan, GreaterThanOrEqual, LessThan, or LessThanOrEqual, e.g. a join/eq condition incorrectly mapped to a dynamic filter.

Common situations: Frontend planner mapping an equality predicate to a dynamic filter node; users writing queries whose plan lands an unsupported comparator into the dynamic filter path; version skew where new comparators are planned but the stream side is older.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at src/stream/src/from_proto/dynamic_filter.rs:50

    type Node = DynamicFilterNode;

    async fn new_boxed_executor(
        params: ExecutorParams,
        node: &Self::Node,
        store: impl StateStore,
    ) -> StreamResult<Executor> {
        let [source_l, source_r]: [_; 2] = params.input.try_into().unwrap();
        let key_l = node.get_left_key() as usize;

        let vnodes = params.vnode_bitmap.map(Arc::new);

        let prost_condition = node.get_condition()?;
        let comparator = prost_condition.get_function_type()?;
        if !matches!(
            comparator,
            GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual
        ) {
            bail!(
                "`DynamicFilterExecutor` only supports comparators:\
                GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual",
            );
        }

        let state_table_r = StateTableBuilder::new(node.get_right_table()?, store.clone(), None)
            .enable_preload_all_rows_by_config(&params.config)
            .build()
            .await;

        let left_table = node.get_left_table()?;
        let cleaned_by_watermark = node.cleaned_by_watermark
            || #[expect(deprecated)]
            left_table.cleaned_by_watermark;
        let state_table_l = StateTableBuilder::new(node.get_left_table()?, store, vnodes)
            .enable_preload_all_rows_by_config(&params.config)
            .build()
            .await;

View on GitHub (pinned to 6469eb736d)