risingwavelabs/risingwave · error
invalid MATCH_RECOGNIZE pattern: {e}
Error message
invalid MATCH_RECOGNIZE pattern: {e} What it means
This error wraps a failure while decoding the MATCH_RECOGNIZE pattern from its protobuf representation into the in-memory pattern AST during stream executor construction. `pattern_from_protobuf` failed to convert the serialized pattern node (variables, concatenation, quantifiers, etc.), so the executor refuses to build. It exists to preserve the underlying parse/decode error context rather than panic.
Source
Thrown at src/stream/src/from_proto/match_recognize.rs:110
}
let defines = node
.defines
.iter()
.map(|d| CompiledDefine::from_protobuf(d, params.eval_error_report.clone()))
.collect::<crate::executor::StreamExecutorResult<Vec<_>>>()?;
let measures = node
.measures
.iter()
.map(|m| CompiledMeasure::from_protobuf(m, params.eval_error_report.clone()))
.collect::<crate::executor::StreamExecutorResult<Vec<_>>>()?;
let pattern_node = node
.pattern_node
.as_ref()
.ok_or_else(|| anyhow::anyhow!("MATCH_RECOGNIZE node missing pattern"))?;
let pattern = pattern_from_protobuf(pattern_node)
.map_err(|e| anyhow::anyhow!("invalid MATCH_RECOGNIZE pattern: {e}"))?;
let nfa = Nfa::compile(&pattern);
// Fail fast on anything malformed rather than silently defaulting to PAST LAST ROW, which
// would mask a corrupt plan or a version skew.
let skip = {
use risingwave_pb::stream_plan::match_recognize_after_match_skip::Mode;
let pb_skip = node
.after_match_skip
.as_ref()
.ok_or_else(|| anyhow::anyhow!("MATCH_RECOGNIZE node missing after_match_skip"))?;
let target = || {
pb_skip.target.clone().ok_or_else(|| {
anyhow::anyhow!("AFTER MATCH SKIP TO FIRST/LAST missing its target variable")
})
};
match pb_skip.mode() {
Mode::PastLastRow => SkipMode::PastLastRow,
Mode::ToNextRow => SkipMode::ToNextRow,View on GitHub (pinned to 6469eb736d)
Solutions
- Read the inner error text (the `{e}` part) to find which pattern element failed to decode.
- Verify meta and stream node versions match; restart the cluster so all nodes run the same build.
- Recreate or refresh the affected streaming job (e.g. ALTER/refresh the materialized view or re-issue the CREATE MATERIALIZED VIEW) so the plan is regenerated.
- If reproducible, file a bug with the plan — a valid binder-produced pattern should always decode.
Example fix
// before: opaque error
.map_err(|e| anyhow::anyhow!("invalid MATCH_RECOGNIZE pattern: {e}"))?
// after: include the offending pattern for diagnosis
.map_err(|e| anyhow::anyhow!("invalid MATCH_RECOGNIZE pattern {:?}: {e}", pattern_node))? Defensive patterns
Strategy: try-catch
Validate before calling
// Before relying on the executor, sanity-check the pattern proto is present and well-formed
fn pattern_valid(node: &MatchRecognizeNode) -> bool {
node.pattern_node.is_some()
} Try / catch
// Rust: executor construction returns Result; surface the context, don't unwrap
let exec = MatchRecognizeExecutor::new(...).map_err(|e| {
tracing::error!("MATCH_RECOGNIZE executor build failed: {e:#}");
e
})?; Prevention
- Keep meta and compute nodes on the same version; avoid rolling upgrades across pattern-feature boundaries.
- Always generate plans via the binder/frontend, never hand-craft protos.
- Add round-trip tests: proto -> pattern -> proto for all supported MATCH_RECOGNIZE constructs.
When it happens
Trigger: Calling `MatchRecognizeExecutor::new` (via `new_boxed_executor`) with a stream plan whose `pattern_node` is present but whose nested pattern proto fails `pattern_from_protobuf` — e.g. malformed pattern fields, unknown enum variants, or an incompatible proto schema version.
Common situations: Version skew between the meta node (plan producer) and stream node (plan consumer) after a rolling upgrade; a corrupt or hand-edited serialized plan; a newly added pattern construct understood by the binder/frontend but not yet by the older proto decoder on the compute node.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- unknown MATCH_RECOGNIZE input mode: {}
- MATCH_RECOGNIZE node missing after_match_skip
- invalid MATCH_RECOGNIZE after_match_skip mode: {}
- Node {} cannot be convert to stream node
- Failed to decode prost: field not found `{}`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/acf652bbaf663657.
Report an issue: GitHub.