{"record":{"id":"b64c3f5742495ea0","repo":"risingwavelabs/risingwave","slug":"match-recognize-order-by-column-is-out-of-range","errorCode":null,"errorMessage":"MATCH_RECOGNIZE ORDER BY column {} is out of range for an input of {} columns","messagePattern":"MATCH_RECOGNIZE ORDER BY column (.+?) is out of range for an input of (.+?) columns","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/from_proto/match_recognize.rs","lineNumber":184,"sourceCode":"            return Err(anyhow::anyhow!(\n                \"MATCH_RECOGNIZE carries only one of the two WITHIN expressions \\\n                 (predicate: {}, deadline: {}); the binder emits both or neither\",\n                within.is_some(),\n                within_deadline.is_some(),\n            )\n            .into());\n        }\n        // The deadline is compared directly against the order key and the watermark\n        // (`ScalarRefImpl::default_cmp` panics across variants — an actor crash loop that recovery\n        // replays), and the span predicate is a boolean. The binder guarantees both\n        // (`lower_within`); re-state it here so a skewed or corrupt plan fails at build time.\n        let order_key_type = input\n            .schema()\n            .fields\n            .get(order_key_indices[0])\n            .map(|f| f.data_type())\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"MATCH_RECOGNIZE ORDER BY column {} is out of range for an input of {} columns\",\n                    order_key_indices[0],\n                    input.schema().len()\n                )\n            })?;\n        if let Some(deadline) = &within_deadline\n            && deadline.return_type() != order_key_type\n        {\n            return Err(anyhow::anyhow!(\n                \"MATCH_RECOGNIZE WITHIN deadline has type {} but the ORDER BY column has type {}; \\\n                 the two are compared directly\",\n                deadline.return_type(),\n                order_key_type,\n            )\n            .into());\n        }\n        if let Some(predicate) = &within\n            && predicate.return_type() != DataType::Boolean","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/from_proto/match_recognize.rs#L166-L202","documentation":"The executor reads the ORDER BY column index from the plan and looks it up in the input schema to get the ordering column's type. The index exceeds the number of input columns, so the schema lookup fails. This means the plan's order key index is inconsistent with the input schema — a corrupt plan or schema skew.","triggerScenarios":"`new_boxed_executor` receives a MatchRecognizeNode whose `order_key_indices[0]` is >= `input.schema().len()` — e.g. the upstream operator was rewritten to fewer columns while the plan still references the old index.","commonSituations":"Version skew where a plan built against an older schema is replayed on a newer executor; corrupt plan persistence; plan fragments changed by a manual DDL/evolution while the MV plan was not refreshed.","solutions":["Re-create the streaming job (drop and re-issue the CREATE MATERIALIZED VIEW) so plan and schema are rebuilt together.","Align node versions across the cluster to rule out version skew.","Inspect the plan (EXPLAIN) and confirm the ORDER BY column exists on the input relation.","If reproducible, report a planner bug — indices and schema should always agree."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check the order key index is in bounds before building the executor\nfn order_key_in_bounds(idx: usize, schema_len: usize) -> bool {\n    idx < schema_len\n}","typeGuard":null,"tryCatchPattern":"// Bounds-check defensively and log plan vs schema\nlet idx = order_key_indices[0];\nif idx >= input.schema().len() {\n    return Err(anyhow!(\"ORDER BY index {idx} out of range for schema len {}\", input.schema().len()));\n}","preventionTips":["Recreate materialized views after schema-changing DDL instead of relying on stale plans.","Keep cluster versions uniform so plan indices match schema layout.","Add planner tests asserting order-key indices fall within the input schema."],"tags":["streaming","match-recognize","schema","index-out-of-range"],"backgroundTag":"index-out-of-range","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"}