{"record":{"id":"0cbab39bebfddf69","repo":"risingwavelabs/risingwave","slug":"dynamicfilterexecutor-only-supports-comparators","errorCode":null,"errorMessage":"`DynamicFilterExecutor` only supports comparators: GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual","messagePattern":"`DynamicFilterExecutor` only supports comparators: GreaterThan \\| GreaterThanOrEqual \\| LessThan \\| LessThanOrEqual","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/from_proto/dynamic_filter.rs","lineNumber":50,"sourceCode":"    type Node = DynamicFilterNode;\n\n    async fn new_boxed_executor(\n        params: ExecutorParams,\n        node: &Self::Node,\n        store: impl StateStore,\n    ) -> StreamResult<Executor> {\n        let [source_l, source_r]: [_; 2] = params.input.try_into().unwrap();\n        let key_l = node.get_left_key() as usize;\n\n        let vnodes = params.vnode_bitmap.map(Arc::new);\n\n        let prost_condition = node.get_condition()?;\n        let comparator = prost_condition.get_function_type()?;\n        if !matches!(\n            comparator,\n            GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual\n        ) {\n            bail!(\n                \"`DynamicFilterExecutor` only supports comparators:\\\n                GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual\",\n            );\n        }\n\n        let state_table_r = StateTableBuilder::new(node.get_right_table()?, store.clone(), None)\n            .enable_preload_all_rows_by_config(&params.config)\n            .build()\n            .await;\n\n        let left_table = node.get_left_table()?;\n        let cleaned_by_watermark = node.cleaned_by_watermark\n            || #[expect(deprecated)]\n            left_table.cleaned_by_watermark;\n        let state_table_l = StateTableBuilder::new(node.get_left_table()?, store, vnodes)\n            .enable_preload_all_rows_by_config(&params.config)\n            .build()\n            .await;","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/from_proto/dynamic_filter.rs#L32-L68","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the frontend so only ordering comparators are planned as dynamic filters.","Rewrite the query so the predicate uses >, >=, <, or <= against the filter column.","Upgrade stream/frontend components together so comparator support matches."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before constructing the node\nlet ok = matches!(comparator, GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual);\nif !ok { /* plan it as a regular filter instead of a dynamic filter */ }","typeGuard":"fn is_supported_comparator(c: ExprType) -> bool {\n    matches!(c, GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual)\n}","tryCatchPattern":null,"preventionTips":["Only map ordering comparators to DynamicFilter in the planner","Add planner assertions when lowering join/filter conditions","Keep frontend and stream comparator enums in sync"],"tags":["streaming","dynamic-filter","planner"],"backgroundTag":"invalid-enum-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}