{"record":{"id":"51a572ecb2a99723","repo":"risingwavelabs/risingwave","slug":"invalid-match-recognize-after-match-skip-mode","errorCode":null,"errorMessage":"invalid MATCH_RECOGNIZE after_match_skip mode: {}","messagePattern":"invalid MATCH_RECOGNIZE after_match_skip mode: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/from_proto/match_recognize.rs","lineNumber":132,"sourceCode":"        // would mask a corrupt plan or a version skew.\n        let skip = {\n            use risingwave_pb::stream_plan::match_recognize_after_match_skip::Mode;\n            let pb_skip = node\n                .after_match_skip\n                .as_ref()\n                .ok_or_else(|| anyhow::anyhow!(\"MATCH_RECOGNIZE node missing after_match_skip\"))?;\n            let target = || {\n                pb_skip.target.clone().ok_or_else(|| {\n                    anyhow::anyhow!(\"AFTER MATCH SKIP TO FIRST/LAST missing its target variable\")\n                })\n            };\n            match pb_skip.mode() {\n                Mode::PastLastRow => SkipMode::PastLastRow,\n                Mode::ToNextRow => SkipMode::ToNextRow,\n                Mode::ToFirst => SkipMode::ToFirst(target()?),\n                Mode::ToLast => SkipMode::ToLast(target()?),\n                Mode::Unspecified => {\n                    return Err(anyhow::anyhow!(\n                        \"invalid MATCH_RECOGNIZE after_match_skip mode: {}\",\n                        pb_skip.mode\n                    )\n                    .into());\n                }\n            }\n        };\n\n        let within = node\n            .within\n            .as_ref()\n            .map(|e| build_non_strict_from_prost(e, params.eval_error_report.clone()))\n            .transpose()?;\n        // Over `DeadlineErrorReport`, not the actor's report directly: `first + bound` leaving the\n        // order key's range is the window that never closes, not a compute error to count and log\n        // per row. See `eval_deadline` in the executor.\n        let within_deadline = node\n            .within_deadline","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/from_proto/match_recognize.rs#L114-L150","documentation":"The proto enum `after_match_skip.mode` is `Unspecified`, meaning the producer never set a valid skip mode. The decoder maps PastLastRow/ToNextRow/ToFirst/ToLast to executor `SkipMode`s and treats Unspecified as invalid input. Proto3 leaves scalar/enum defaults at 0, so this usually indicates an unset field.","triggerScenarios":"`new_boxed_executor` receives an `after_match_skip` whose `mode` is `MODE_UNSPECIFIED` (0) — typically from a hand-built proto, an older producer that set the message but not the mode, or corrupted serialization.","commonSituations":"Version skew after adding the skip enum; test fixtures constructing AfterMatchSkip without setting `mode`; plans from a foreign/hand-crafted producer.","solutions":["Set an explicit mode on the AfterMatchSkip proto (e.g. `mode: PAST_LAST_ROW`).","If writing SQL, add an `AFTER MATCH SKIP ...` clause so the binder emits a concrete mode.","Re-create the streaming job to regenerate the plan with a current binder.","Check for version skew between producer and consumer nodes."],"exampleFix":"// before\nAfterMatchSkip { mode: Mode::Unspecified as i32, target: None }\n// after\nAfterMatchSkip { mode: Mode::PastLastRow as i32, target: None }","handlingStrategy":"validation","validationCode":"// Check the mode is a known value before decoding\nfn skip_mode_valid(skip: &AfterMatchSkip) -> bool {\n    use risingwave_pb::stream_plan::match_recognize_after_match_skip::Mode;\n    !matches!(skip.mode(), Mode::Unspecified)\n}","typeGuard":null,"tryCatchPattern":"// Wrap decode errors with the offending raw value\nlet mode = Mode::try_from(pb_skip.mode)\n    .map_err(|e| anyhow!(\"unknown after_match_skip mode {}: {e}\", pb_skip.mode))?;","preventionTips":["Always set the mode explicitly when constructing AfterMatchSkip protos.","In SQL, include an AFTER MATCH SKIP clause; don't rely on proto defaults.","Use exhaustive match on Mode in producers so new variants are handled."],"tags":["streaming","match-recognize","enum","protobuf"],"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"}