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 = node

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check the SQL: `AFTER MATCH SKIP TO FIRST/LAST` must name a pattern variable, e.g. `SKIP TO LAST b`.
  2. Re-create the streaming job so the plan is regenerated by the current binder.
  3. Align cluster node versions (restart meta and compute nodes).
  4. 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

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/800895b5cab770f2. Report an issue: GitHub.