risingwavelabs/risingwave · error
MATCH_RECOGNIZE carries only one of the two WITHIN expressio
Error message
MATCH_RECOGNIZE carries only one of the two WITHIN expressions (predicate: {}, deadline: {}); the binder emits both or neither What it means
MATCH_RECOGNIZE WITHIN support is expressed as a pair: a span predicate (`within`) and a cached deadline expression (`within_deadline`). The binder always emits both or neither; the executor detects a plan carrying exactly one and rejects it. This guards against a silent behavior change: with only `within` present, the executor would evaluate the deadline path and reject every candidate row, making the view return zero rows forever.
Source
Thrown at src/stream/src/from_proto/match_recognize.rs:166
// per row. See `eval_deadline` in the executor.
let within_deadline = node
.within_deadline
.as_ref()
.map(|e| {
build_non_strict_from_prost(
e,
DeadlineErrorReport::new(params.eval_error_report.clone()),
)
})
.transpose()?;
// The two WITHIN expressions are a correctness-coupled pair, and the coupling tightened when
// the executor's span check started reading the cached deadline instead of evaluating the
// predicate: `within` present with `within_deadline` absent now rejects EVERY candidate, so
// the view would silently produce zero rows. The binder only ever emits both or neither
// (`lower_within`), so a plan carrying one is corrupt — fail loud, as the rest of this
// decoder does, rather than emitting nothing forever.
if within.is_some() != within_deadline.is_some() {
return Err(anyhow::anyhow!(
"MATCH_RECOGNIZE carries only one of the two WITHIN expressions \
(predicate: {}, deadline: {}); the binder emits both or neither",
within.is_some(),
within_deadline.is_some(),
)
.into());
}
// The deadline is compared directly against the order key and the watermark
// (`ScalarRefImpl::default_cmp` panics across variants — an actor crash loop that recovery
// replays), and the span predicate is a boolean. The binder guarantees both
// (`lower_within`); re-state it here so a skewed or corrupt plan fails at build time.
let order_key_type = input
.schema()
.fields
.get(order_key_indices[0])
.map(|f| f.data_type())
.ok_or_else(|| {
anyhow::anyhow!(View on GitHub (pinned to 6469eb736d)
Solutions
- Align cluster node versions so producer and consumer agree on the WITHIN encoding (restart meta and compute nodes).
- Re-create the streaming job so the plan is regenerated with both fields.
- If constructing the node in a test, set both `within` and `within_deadline` (or neither).
- If reproducible on matching versions, report a plan-serialization bug.
Example fix
// before (test fixture)
MatchRecognizeNode { within: Some(predicate), within_deadline: None, .. }
// after
MatchRecognizeNode { within: Some(predicate), within_deadline: Some(deadline), .. } Defensive patterns
Strategy: validation
Validate before calling
// Pair-check before executor construction
fn within_pair_ok(node: &MatchRecognizeNode) -> bool {
node.within.is_some() == node.within_deadline.is_some()
} Try / catch
// Fail with context rather than silently defaulting
if node.within.is_some() != node.within_deadline.is_some() {
return Err(anyhow!("WITHIN predicate/deadline mismatch in MATCH_RECOGNIZE plan"));
} Prevention
- Emit both WITHIN fields from a single code path (binder's lower_within) so they can't diverge.
- Add a proto-level invariant test that within.is_some() == within_deadline.is_some().
- Avoid rolling upgrades across WITHIN-encoding changes.
When it happens
Trigger: `new_boxed_executor` decodes a MatchRecognizeNode where the Option-ness of `within` and `within_deadline` differ (one is Some, the other None).
Common situations: Version skew between a producer that serializes only one field and a consumer that requires both; corrupted plan persistence; a hand-built proto in tests missing one of the two fields.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- MATCH_RECOGNIZE WITHIN deadline has type {} but the ORDER BY
- core predicate must exist
- checked above
- should not receive barrier with epoch {barrier_epoch:?} late
- snapshot backfill paused, but received snapshot chunk
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/773b0dd998a758a1.
Report an issue: GitHub.