{"record":{"id":"4a3a19df3dfc409e","repo":"risingwavelabs/risingwave","slug":"checked-above","errorCode":null,"errorMessage":"checked above","messagePattern":"checked above","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/optimizer/plan_node/logical_match_recognize.rs","lineNumber":220,"sourceCode":"        use crate::error::ErrorCode;\n        use crate::expr::{ExprType, FunctionCall, InputRef};\n        use crate::optimizer::property::RequiredDist;\n        use crate::utils::Condition;\n        // v1 restrictions: PARTITION BY / ORDER BY must be plain columns, PARTITION BY non-empty.\n        // `NotSupported(cause, hint)` throughout, matching this feature's binder-side validation.\n        if self.core.partition_key_indices().is_none() || self.core.order_key_indices().is_none() {\n            return Err(ErrorCode::NotSupported(\n                \"MATCH_RECOGNIZE with an expression in PARTITION BY or ORDER BY\".to_owned(),\n                \"use plain column references; compute the expression in a view below and \\\n                 partition/order by the resulting column\"\n                    .to_owned(),\n            )\n            .into());\n        }\n        if self\n            .core\n            .partition_key_indices()\n            .expect(\"checked above\")\n            .is_empty()\n        {\n            return Err(ErrorCode::NotSupported(\n                \"MATCH_RECOGNIZE without a PARTITION BY\".to_owned(),\n                \"add PARTITION BY; for a global pattern, partition by a constant column computed \\\n                 in a view below (all rows then match within one partition)\"\n                    .to_owned(),\n            )\n            .into());\n        }\n        let order_indices = self.core.order_key_indices().expect(\"checked above\");\n        let Some(&time_col) = order_indices.first() else {\n            bail!(\"MATCH_RECOGNIZE requires an ORDER BY clause\");\n        };\n        let partition_key_indices = self.core.partition_key_indices().expect(\"checked above\");\n\n        let stream_input = self.input().to_stream(ctx)?;\n        // The executor matches over an append-only sequence and emits insert-only results; it has no","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/optimizer/plan_node/logical_match_recognize.rs#L202-L238","documentation":"`to_stream` on `LogicalMatchRecognize` calls `.expect(\"checked above\")` on `partition_key_indices()`, which returns `None` here. An earlier check in the stream-planning entry point is supposed to have already rejected a `MATCH_RECOGNIZE` without `PARTITION BY`, so hitting this expect means the earlier guard did not run on this code path.","triggerScenarios":"Planning a streaming `MATCH_RECOGNIZE` whose logical node lacks partition key indices, bypassing or skipping the earlier `to_stream` pre-check that raises `NotSupported(\"MATCH_RECOGNIZE without a PARTITION BY\")`.","commonSituations":"A `MATCH_RECOGNIZE` query reaches this node through an unexpected planning entry point (e.g. `logical_rewrite_for_stream` output, tests, or a partially-validated plan) instead of the guarded `to_stream` path.","solutions":["Ensure `MATCH_RECOGNIZE` queries include a `PARTITION BY` clause so `partition_key_indices()` returns `Some`.","Route planning through the normal `to_stream` entry point that performs the pre-check instead of constructing/reusing the node ad hoc.","If the panic occurs despite the pre-check, inspect which entry point skipped it and file a bug with the query."],"exampleFix":"-- before: no PARTITION BY triggers the checked-above invariant\nSELECT * FROM t MATCH_RECOGNIZE (ORDER BY ts ...) ;\n-- after\nSELECT * FROM t MATCH_RECOGNIZE (PARTITION BY id ORDER BY ts ...) ;","handlingStrategy":"validation","validationCode":"// SQL-side guard: always include PARTITION BY in MATCH_RECOGNIZE\n// SELECT * FROM t MATCH_RECOGNIZE (PARTITION BY id ORDER BY ts PATTERN ...)","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"PARTITION BY\") => eprintln!(\"Add PARTITION BY to MATCH_RECOGNIZE\"),\n    r => r?,\n}","preventionTips":["Always write `PARTITION BY` (or partition by a constant for global patterns) inside MATCH_RECOGNIZE.","Plan through the normal CREATE MATERIALIZED VIEW path so the friendly pre-check error fires instead of an expect panic."],"tags":["rust","match-recognize","invariant","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}