{"record":{"id":"4f1b742d844cbe06","repo":"risingwavelabs/risingwave","slug":"offset-of-rowsframebound-must-be-integer","errorCode":null,"errorMessage":"offset of `RowsFrameBound` must be `Integer`","messagePattern":"offset of `RowsFrameBound` must be `Integer`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/core/src/window_function/rows.rs","lineNumber":103,"sourceCode":"impl FrameBoundsImpl for RowsFrameBounds {\n    fn validate(&self) -> Result<()> {\n        FrameBound::validate_bounds(&self.start, &self.end, |_| Ok(()))\n    }\n}\n\npub type RowsFrameBound = FrameBound<usize>;\n\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 {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/core/src/window_function/rows.rs#L85-L121","documentation":"The legacy protobuf `RowsFrameBound` carried offsets as a oneof: either an Integer or a Datum. ROWS frames count rows, so the offset must be an integer row count; a Datum offset is only meaningful for RANGE frames. The decoder rejects Datum offsets explicitly.","triggerScenarios":"Calling `from_protobuf_legacy` on a `RowsFrameBound` whose protobuf oneof `offset` is set to the `Datum` variant instead of `Integer`.","commonSituations":"Plan fragments produced by an old or altered frontend that encoded the frame offset as a literal datum; hand-crafted or corrupted protobuf payloads.","solutions":["Regenerate the plan so the frontend emits the offset as `PbOffset::Integer`","If you must handle Datum offsets, convert them to integers before deserialization or use the non-legacy path","Verify frontend/backend versions agree on frame bound encoding"],"exampleFix":"// before: datum offset in RowsFrameBound proto\n// offset { datum { ... } }\n// after: integer offset\n// offset { integer: 3 }","handlingStrategy":"validation","validationCode":"fn valid_rows_offset(b: &PbRowsFrameBoundLegacy) -> bool {\n    matches!(b.offset, Some(PbOffset::Integer(_)))\n}","typeGuard":"fn has_integer_offset(o: &PbOffset) -> bool { matches!(o, PbOffset::Integer(_)) }","tryCatchPattern":"match RowsFrameBound::from_protobuf_legacy(&pb) {\n    Ok(b) => b,\n    Err(e) if e.to_string().contains(\"must be `Integer`\") => return Err(anyhow!(\"ROWS frame offset must be an integer literal\")),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Always emit integer offsets for ROWS frames in the frontend","Avoid the legacy oneof encoding; use the current PbRowsFrameBound","Validate plan fragments before deserialization"],"tags":["rust","window-function","protobuf"],"backgroundTag":"protobuf-unmarshal-failed","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"}