risingwavelabs/risingwave · error
MATCH_RECOGNIZE only supports the default ascending ORDER BY
Error message
MATCH_RECOGNIZE only supports the default ascending ORDER BY, got {:?} What it means
MATCH_RECOGNIZE v1 supports only the default ascending ORDER BY on its event-time column. During decode, each ORDER BY entry is converted to a `ColumnOrder`; if any entry's `order_type` is not ascending, the executor refuses to build, since descending/other orderings are not implemented in the NFA event-time handling.
Source
Thrown at src/stream/src/from_proto/match_recognize.rs:79
MatchRecognizeInputMode::Unspecified | MatchRecognizeInputMode::EventTime => {}
other => {
return Err(
anyhow::anyhow!("unsupported MATCH_RECOGNIZE input mode: {other:?}").into(),
);
}
}
let partition_key_indices = node.partition_by.iter().map(|&i| i as usize).collect();
// ORDER BY is carried as `ColumnOrder`. v1 only supports the default ascending order (the
// binder rejects anything else); assert it here too so a non-ascending plan fails fast
// rather than being silently sorted ascending by the executor.
let order_key_indices = node
.order_by
.iter()
.map(|c| {
let co = ColumnOrder::from_protobuf(c);
if co.order_type != OrderType::ascending() {
return Err(anyhow::anyhow!(
"MATCH_RECOGNIZE only supports the default ascending ORDER BY, got {:?}",
co.order_type
)
.into());
}
Ok(co.column_index)
})
.collect::<StreamResult<Vec<usize>>>()?;
// The executor reads the leading ORDER BY column unconditionally; an empty list is a
// corrupt plan and must fail here, not index-panic there.
if order_key_indices.is_empty() {
return Err(anyhow::anyhow!("MATCH_RECOGNIZE plan carries an empty ORDER BY").into());
}
let defines = node
.defines
.iter()
.map(|d| CompiledDefine::from_protobuf(d, params.eval_error_report.clone()))View on GitHub (pinned to 6469eb736d)
Solutions
- Rewrite the MATCH_RECOGNIZE ORDER BY to use ascending order (the default), e.g. `ORDER BY ts` not `ORDER BY ts DESC`.
- If reverse ordering is intended, invert the pattern logic instead of the sort direction.
- Check the frontend version and re-plan if an older planner emitted a non-ascending order type.
- Implement descending-order support in the executor if it becomes a product requirement.
Example fix
-- before MATCH_RECOGNIZE ( ORDER BY ts DESC ... ) -- after MATCH_RECOGNIZE ( ORDER BY ts ... )
Defensive patterns
Strategy: validation
Validate before calling
-- SQL guard: ascending-only ORDER BY inside MATCH_RECOGNIZE MATCH_RECOGNIZE ( ORDER BY ts ASC ... ) -- never ORDER BY ts DESC
Type guard
fn is_ascending(co: &ColumnOrder) -> bool { co.order_type == OrderType::ascending() } Try / catch
if co.order_type != OrderType::ascending() { return Err(anyhow!("MATCH_RECOGNIZE only supports the default ascending ORDER BY, got {:?}", co.order_type).into()); } Prevention
- Omit the direction keyword in MATCH_RECOGNIZE ORDER BY (default is ascending).
- Add a frontend planner check that rejects DESC in MATCH_RECOGNIZE early with a clear message.
- Cover ORDER BY variants in planner tests.
When it happens
Trigger: `new_boxed_executor` decodes `node.order_by` and encounters a `ColumnOrder` whose `order_type` differs from `OrderType::ascending()` — e.g. the frontend emitted `ORDER BY ts DESC` inside MATCH_RECOGNIZE.
Common situations: Writing `MATCH_RECOGNIZE ( ORDER BY ts DESC ... )` in SQL; planner bugs emitting non-default order types; plan proto hand-editing or version skew introducing new order types.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Expression error: {0}
- unknown MATCH_RECOGNIZE input mode: {}
- unsupported MATCH_RECOGNIZE input mode: {other:?}
- MATCH_RECOGNIZE plan carries an empty ORDER BY
- MATCH_RECOGNIZE node missing pattern
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/d2623500ed38e928.
Report an issue: GitHub.