{"record":{"id":"49bd835c129aeb18","repo":"risingwavelabs/risingwave","slug":"unspecified-type-of-rowsframebound","errorCode":null,"errorMessage":"unspecified type of `RowsFrameBound`","messagePattern":"unspecified type of `RowsFrameBound`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/core/src/window_function/rows.rs","lineNumber":110,"sourceCode":"\nimpl RowsFrameBound {\n    pub(super) fn from_protobuf_legacy(bound: &PbBound) -> Result<Self> {\n        use risingwave_pb::expr::window_frame::bound::PbOffset;\n\n        let offset = bound.get_offset()?;\n        let bound = match offset {\n            PbOffset::Integer(offset) => Self::from_protobuf(&PbRowsFrameBound {\n                r#type: bound.get_type()? as _,\n                offset: Some(*offset),\n            })?,\n            PbOffset::Datum(_) => bail!(\"offset of `RowsFrameBound` must be `Integer`\"),\n        };\n        Ok(bound)\n    }\n\n    fn from_protobuf(bound: &PbRowsFrameBound) -> Result<Self> {\n        let bound = match bound.get_type()? {\n            PbBoundType::Unspecified => bail!(\"unspecified type of `RowsFrameBound`\"),\n            PbBoundType::UnboundedPreceding => Self::UnboundedPreceding,\n            PbBoundType::Preceding => Self::Preceding(*bound.get_offset()? as usize),\n            PbBoundType::CurrentRow => Self::CurrentRow,\n            PbBoundType::Following => Self::Following(*bound.get_offset()? as usize),\n            PbBoundType::UnboundedFollowing => Self::UnboundedFollowing,\n        };\n        Ok(bound)\n    }\n\n    fn to_protobuf(&self) -> PbRowsFrameBound {\n        let (r#type, offset) = match self {\n            Self::UnboundedPreceding => (PbBoundType::UnboundedPreceding, None),\n            Self::Preceding(offset) => (PbBoundType::Preceding, Some(*offset as _)),\n            Self::CurrentRow => (PbBoundType::CurrentRow, None),\n            Self::Following(offset) => (PbBoundType::Following, Some(*offset as _)),\n            Self::UnboundedFollowing => (PbBoundType::UnboundedFollowing, None),\n        };\n        PbRowsFrameBound {","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/core/src/window_function/rows.rs#L92-L128","documentation":"`RowsFrameBound::from_protobuf` matches the protobuf bound type enum exhaustively; the `Unspecified` variant (proto3 default for unset enum fields) is not a valid frame bound type, so it is rejected. This guards against deserializing a frame bound whose `type` field was never set.","triggerScenarios":"Deserializing a `PbRowsFrameBound` where `r#type` is UNSPECIFIED (0) — i.e. the field was omitted or defaulted in the serialized plan.","commonSituations":"Protobuf messages constructed programmatically without setting the type field; older/other producers that don't populate required enums; corrupted plan fragments.","solutions":["Ensure the frontend sets `r#type` to one of UnboundedPreceding/Preceding/CurrentRow/Following/UnboundedFollowing before serialization","Regenerate the plan with a matching frontend version","Validate the plan fragment before deserialization"],"exampleFix":"// before (proto)\n// rows_frame_bound { offset: 3 }            // type unset -> UNSPECIFIED\n// after (proto)\n// rows_frame_bound { type: PRECEDING, offset: 3 }","handlingStrategy":"validation","validationCode":"fn bound_type_set(t: i32) -> bool { t != 0 } // 0 = UNSPECIFIED","typeGuard":"fn is_specified(t: PbBoundType) -> bool { !matches!(t, PbBoundType::Unspecified) }","tryCatchPattern":"match RowsFrameBound::from_protobuf(&pb) {\n    Ok(b) => b,\n    Err(e) if e.to_string().contains(\"unspecified type\") => return Err(anyhow!(\"frame bound type missing in plan\")),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Always set `r#type` explicitly when constructing PbRowsFrameBound","Enable proto linting that rejects enum field defaults","Round-trip test plans through serialize/deserialize"],"tags":["rust","window-function","protobuf","enum"],"backgroundTag":"invalid-enum-value","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"}