risingwavelabs/risingwave · error
MATCH_RECOGNIZE define missing condition
Error message
MATCH_RECOGNIZE define missing condition
What it means
When deserializing a MATCH_RECOGNIZE DEFINE slot from protobuf, the condition expression (`pb.condition`) is absent. Each DEFINE row pattern needs a concrete boolean condition to evaluate candidates, so the executor fails deserialization rather than building a define that matches everything.
Source
Thrown at src/stream/src/executor/match_recognize/executor.rs:357
offset: usize,
}
/// A `DEFINE` predicate compiled for execution: a boolean condition over a synthetic slot row.
pub struct CompiledDefine {
symbol: String,
condition: NonStrictExpression,
slots: Vec<DefineSlot>,
}
impl CompiledDefine {
pub fn from_protobuf(
pb: &PbMatchRecognizeDefine,
error_report: impl EvalErrorReport + 'static,
) -> StreamExecutorResult<Self> {
let condition = build_non_strict_from_prost(
pb.condition
.as_ref()
.ok_or_else(|| anyhow::anyhow!("MATCH_RECOGNIZE define missing condition"))?,
error_report,
)?;
let slots = pb
.slots
.iter()
.map(|s| {
let kind = s.kind();
// The binder rejects physical NEXT in DEFINE (a verdict depending on rows after
// the candidate needs per-candidate decidability), so no plan this frontend
// produces carries it — reject rather than evaluate a watermark-unsafe,
// arrival-order-dependent read from a skewed plan. UNSPECIFIED (also what an
// out-of-range wire value decodes to) fails fast rather than silently changing
// the predicate's meaning. Every later match on the kind relies on this.
if kind == DefineSlotKind::Next {
return Err(StreamExecutorError::from(anyhow::anyhow!(
"physical NEXT in a MATCH_RECOGNIZE DEFINE is not supported"
)));
}View on GitHub (pinned to 6469eb736d)
Solutions
- Re-create the query/MV so the frontend regenerates a complete plan.
- Check for version skew between frontend and stream compute and upgrade consistently.
- When crafting protobufs in tests, always set condition on DEFINE slots.
Example fix
// before
PbMatchRecognizeDefine { slots: ..., condition: None }
// after
PbMatchRecognizeDefine { slots: ..., condition: Some(condition_proto) } Defensive patterns
Strategy: validation
Validate before calling
// Validate before building the define slot:
if define.condition.is_none() {
return Err(anyhow!("DEFINE '{}' has no condition", define.pattern));
} Try / catch
// Catch missing-condition at plan load and regenerate:
match DefineSlot::from_protobuf(&pb, &report) {
Err(e) if e.to_string().contains("define missing condition") => re_plan_or_recreate_job(),
r => r,
} Prevention
- Always emit a condition for every DEFINE pattern in the frontend.
- Use builder helpers that make condition required.
- Round-trip test DEFINE protobufs.
When it happens
Trigger: DefineSlot::from_protobuf called with a PbMatchRecognizeDefine whose condition field is None.
Common situations: Corrupt or hand-edited plan protobuf; frontend/backend version skew losing the field; manually built prost messages in tests.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- MATCH_RECOGNIZE measure missing expression
- invalid MATCH_RECOGNIZE measure slot kind: {}
- MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call
- invalid MATCH_RECOGNIZE define slot kind: {}
- unspecified AsOf join inequality type
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/3e49742ea345262b.
Report an issue: GitHub.