risingwavelabs/risingwave · error

MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call

Error message

MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call

What it means

A MATCH_RECOGNIZE measure slot of kind SUM or AVG must carry an agg_call protobuf from which the streaming aggregation kernel is built. When `s.agg_call` is None, the executor cannot construct the kernel and fails deserialization.

Source

Thrown at src/stream/src/executor/match_recognize/executor.rs:216

            .slots
            .iter()
            .map(|s| {
                let kind = s.kind();
                // Fail fast rather than silently changing measure semantics under a corrupt plan
                // or version skew. (An out-of-range wire value decodes as UNSPECIFIED via
                // `s.kind()`.) Every later match on the kind relies on this rejection.
                if kind == MeasureSlotKind::Unspecified {
                    return Err(anyhow::anyhow!(
                        "invalid MATCH_RECOGNIZE measure slot kind: {}",
                        s.kind
                    )
                    .into());
                }
                let agg = match kind {
                    MeasureSlotKind::Sum => {
                        let call =
                            AggCall::from_protobuf(s.agg_call.as_ref().ok_or_else(|| {
                                anyhow::anyhow!(
                                    "MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call"
                                )
                            })?)?;
                        let col_type = call.args.arg_types()[0].clone();
                        let func = build_append_only(&call)?;
                        Some(AggSlot { func, col_type })
                    }
                    _ => None,
                };
                Ok(MeasureSlot {
                    kind,
                    vars: s.vars.clone(),
                    col_idx: s.col_idx as usize,
                    agg,
                })
            })
            .collect::<StreamExecutorResult<Vec<_>>>()?;
        Ok(CompiledMeasure { expr, slots })

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Ensure the frontend populates agg_call for every SUM/AVG measure; re-plan the query after any frontend fix.
  2. Regenerate the plan by dropping and recreating the MV/query.
  3. In tests, provide a fully-formed PbAggCall in the slot's agg_call field.

Example fix

// before
PbMeasureSlot { kind: SUM, agg_call: None }
// after
PbMeasureSlot { kind: SUM, agg_call: Some(PbAggCall { .. }) }
Defensive patterns

Strategy: validation

Validate before calling

// Validate SUM/AVG slots carry an agg_call before deserialization:
if matches!(s.kind(), MeasureSlotKind::Sum | MeasureSlotKind::Avg) && s.agg_call.is_none() {
    return Err(anyhow!("SUM/AVG measure requires agg_call"));
}

Try / catch

// Handle deserialization failure by re-planning:
match MeasureSlot::from_protobuf(&pb, &report) {
    Err(e) if e.to_string().contains("missing agg_call") => re_plan_or_fail_with_context(e),
    r => r,
}

Prevention

When it happens

Trigger: MeasureSlot::from_protobuf with kind Sum (or Avg) and agg_call unset; AggCall::from_protobuf is called on s.agg_call.as_ref() which is None.

Common situations: Frontend bug omitting agg_call for SUM/AVG measures; plan corruption; hand-written protobufs in tests that set kind but forget agg_call.

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/b0dc1b651f16347c. Report an issue: GitHub.