{"record":{"id":"b0dc1b651f16347c","repo":"risingwavelabs/risingwave","slug":"match-recognize-sum-avg-measure-slot-missing-agg-c","errorCode":null,"errorMessage":"MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call","messagePattern":"MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/executor/match_recognize/executor.rs","lineNumber":216,"sourceCode":"            .slots\n            .iter()\n            .map(|s| {\n                let kind = s.kind();\n                // Fail fast rather than silently changing measure semantics under a corrupt plan\n                // or version skew. (An out-of-range wire value decodes as UNSPECIFIED via\n                // `s.kind()`.) Every later match on the kind relies on this rejection.\n                if kind == MeasureSlotKind::Unspecified {\n                    return Err(anyhow::anyhow!(\n                        \"invalid MATCH_RECOGNIZE measure slot kind: {}\",\n                        s.kind\n                    )\n                    .into());\n                }\n                let agg = match kind {\n                    MeasureSlotKind::Sum => {\n                        let call =\n                            AggCall::from_protobuf(s.agg_call.as_ref().ok_or_else(|| {\n                                anyhow::anyhow!(\n                                    \"MATCH_RECOGNIZE SUM/AVG measure slot missing agg_call\"\n                                )\n                            })?)?;\n                        let col_type = call.args.arg_types()[0].clone();\n                        let func = build_append_only(&call)?;\n                        Some(AggSlot { func, col_type })\n                    }\n                    _ => None,\n                };\n                Ok(MeasureSlot {\n                    kind,\n                    vars: s.vars.clone(),\n                    col_idx: s.col_idx as usize,\n                    agg,\n                })\n            })\n            .collect::<StreamExecutorResult<Vec<_>>>()?;\n        Ok(CompiledMeasure { expr, slots })","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/match_recognize/executor.rs#L198-L234","documentation":"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.","triggerScenarios":"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.","commonSituations":"Frontend bug omitting agg_call for SUM/AVG measures; plan corruption; hand-written protobufs in tests that set kind but forget agg_call.","solutions":["Ensure the frontend populates agg_call for every SUM/AVG measure; re-plan the query after any frontend fix.","Regenerate the plan by dropping and recreating the MV/query.","In tests, provide a fully-formed PbAggCall in the slot's agg_call field."],"exampleFix":"// before\nPbMeasureSlot { kind: SUM, agg_call: None }\n// after\nPbMeasureSlot { kind: SUM, agg_call: Some(PbAggCall { .. }) }","handlingStrategy":"validation","validationCode":"// Validate SUM/AVG slots carry an agg_call before deserialization:\nif matches!(s.kind(), MeasureSlotKind::Sum | MeasureSlotKind::Avg) && s.agg_call.is_none() {\n    return Err(anyhow!(\"SUM/AVG measure requires agg_call\"));\n}","typeGuard":null,"tryCatchPattern":"// Handle deserialization failure by re-planning:\nmatch MeasureSlot::from_protobuf(&pb, &report) {\n    Err(e) if e.to_string().contains(\"missing agg_call\") => re_plan_or_fail_with_context(e),\n    r => r,\n}","preventionTips":["Ensure the planner always attaches AggCall for SUM/AVG measures.","Use round-trip tests covering every MeasureSlotKind.","Never build measure protobufs by hand without agg_call for aggregations."],"tags":["match-recognize","protobuf","aggregation","plan-deserialization"],"backgroundTag":"missing-required-argument","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}