{"record":{"id":"11dc8ad923a13ce9","repo":"risingwavelabs/risingwave","slug":"invalid-match-recognize-measure-slot-kind","errorCode":null,"errorMessage":"invalid MATCH_RECOGNIZE measure slot kind: {}","messagePattern":"invalid MATCH_RECOGNIZE measure slot kind: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/executor/match_recognize/executor.rs","lineNumber":206,"sourceCode":"        pb: &PbMatchRecognizeMeasure,\n        error_report: impl EvalErrorReport + 'static,\n    ) -> StreamExecutorResult<Self> {\n        let expr = build_non_strict_from_prost(\n            pb.expr\n                .as_ref()\n                .ok_or_else(|| anyhow::anyhow!(\"MATCH_RECOGNIZE measure missing expression\"))?,\n            error_report,\n        )?;\n        let slots = pb\n            .slots\n            .iter()\n            .map(|s| {\n                let kind = s.kind();\n                // Fail fast rather than silently changing measure semantics under a corrupt plan\n                // or version skew. (An out-of-range wire value decodes as UNSPECIFIED via\n                // `s.kind()`.) Every later match on the kind relies on this rejection.\n                if kind == MeasureSlotKind::Unspecified {\n                    return Err(anyhow::anyhow!(\n                        \"invalid MATCH_RECOGNIZE measure slot kind: {}\",\n                        s.kind\n                    )\n                    .into());\n                }\n                let agg = match kind {\n                    MeasureSlotKind::Sum => {\n                        let call =\n                            AggCall::from_protobuf(s.agg_call.as_ref().ok_or_else(|| {\n                                anyhow::anyhow!(\n                                    \"MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call\"\n                                )\n                            })?)?;\n                        let col_type = call.args.arg_types()[0].clone();\n                        let func = build_append_only(&call)?;\n                        Some(AggSlot { func, col_type })\n                    }\n                    _ => None,","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/match_recognize/executor.rs#L188-L224","documentation":"A MATCH_RECOGNIZE measure slot's protobuf `kind` field decoded to UNSPECIFIED, meaning the wire value was unset or out of range. Since every later match on the kind relies on it being a concrete aggregation kind, the executor rejects it at deserialization instead of silently changing measure semantics.","triggerScenarios":"MeasureSlot::from_protobuf sees s.kind() == MeasureSlotKind::Unspecified, e.g. an out-of-range i32 in the kind field or kind simply not set.","commonSituations":"Version skew: newer frontend emits a kind value the older backend doesn't know; corrupt plan in meta storage; hand-built prost messages in tests.","solutions":["Align frontend and backend versions so all MeasureSlotKind values are recognized.","Re-create the streaming job to regenerate a valid plan.","In test code, always set a valid kind (Sum/Avg/etc.) on measure slots."],"exampleFix":"// before\nPbMeasureSlot { kind: 99 } // out of range -> UNSPECIFIED\n// after\nPbMeasureSlot { kind: MeasureSlotKind::Sum as i32 }","handlingStrategy":"validation","validationCode":"// Check the kind decodes to a known value before use:\nlet kind = s.kind();\nif kind == MeasureSlotKind::Unspecified {\n    return Err(anyhow!(\"unsupported measure slot kind {}\", s.kind));\n}","typeGuard":null,"tryCatchPattern":"// Catch enum rejection during plan load and regenerate the plan:\nmatch slot_from_protobuf(&pb) {\n    Err(e) if e.to_string().contains(\"invalid MATCH_RECOGNIZE measure slot kind\") => regenerate_plan(),\n    r => r,\n}","preventionTips":["Keep protobuf enum definitions in sync between frontend and backend.","Never send hand-picked integer kind values; use the enum's as-i32 conversion.","Test plans through real serialization round-trips."],"tags":["match-recognize","protobuf","enum","plan-deserialization"],"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-14T16:17:12.679Z"}