risingwavelabs/risingwave · error
AFTER MATCH SKIP TO FIRST/LAST missing its target variable
Error message
AFTER MATCH SKIP TO FIRST/LAST missing its target variable
What it means
When the plan requests `AFTER MATCH SKIP TO FIRST <var>` or `TO LAST <var>`, the proto must carry a `target` variable naming the row to skip to. The decoder found a TO FIRST/TO LAST skip mode with no target variable and rejects the plan. Without the target the skip semantics are undefined, so the executor fails loudly.
Source
Thrown at src/stream/src/from_proto/match_recognize.rs:123
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,
Mode::ToFirst => SkipMode::ToFirst(target()?),
Mode::ToLast => SkipMode::ToLast(target()?),
Mode::Unspecified => {
return Err(anyhow::anyhow!(
"invalid MATCH_RECOGNIZE after_match_skip mode: {}",
pb_skip.mode
)
.into());
}
}
};
let within = nodeView on GitHub (pinned to 6469eb736d)
Solutions
- Check the SQL: `AFTER MATCH SKIP TO FIRST/LAST` must name a pattern variable, e.g. `SKIP TO LAST b`.
- Re-create the streaming job so the plan is regenerated by the current binder.
- Align cluster node versions (restart meta and compute nodes).
- If the SQL is valid and this persists, report a binder/proto bug.
Example fix
// before (SQL) AFTER MATCH SKIP TO LAST // after AFTER MATCH SKIP TO LAST b
Defensive patterns
Strategy: validation
Validate before calling
// SQL-level check: TO FIRST/LAST must name a variable -- validate: pattern has variable v and clause reads SKIP TO FIRST v / SKIP TO LAST v
Try / catch
// Validate mode/target pairing before executor construction
fn validate_skip(skip: &AfterMatchSkip) -> Result<(), String> {
use Mode::*;
match skip.mode() {
ToFirst | ToLast if skip.target.is_none() => Err("TO FIRST/LAST requires target".into()),
_ => Ok(()),
}
} Prevention
- Always write `AFTER MATCH SKIP TO FIRST <var>` / `TO LAST <var>` with an explicit pattern variable.
- Mirror standard SQL semantics: TO FIRST/LAST are meaningless without a target.
- Add frontend tests asserting target is emitted for TO FIRST/TO LAST.
When it happens
Trigger: `new_boxed_executor` decodes a MatchRecognizeNode whose `after_match_skip.mode` is `ToFirst` or `ToLast` while `after_match_skip.target` is `None`.
Common situations: Version skew where the producer did not yet serialize the target field; corrupted or hand-built plan protos; frontend emitting TO FIRST/LAST without a variable (a frontend bug).
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 only supports the default ascending ORDER BY
- MATCH_RECOGNIZE node missing after_match_skip
- Scalar subquery might produce more than one row.
- BatchMatchRecognize is not implemented yet
- MATCH_RECOGNIZE requires an ORDER BY clause
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/800895b5cab770f2.
Report an issue: GitHub.