risingwavelabs/risingwave · error
unspecified type of `RangeFrameBound`
Error message
unspecified type of `RangeFrameBound`
What it means
RangeFrameBound::from_protobuf requires the bound type discriminant to be one of UnboundedPreceding/CurrentRow/UnboundedFollowing/Preceding/Following. An Unspecified type carries no meaning, so the conversion errors instead of defaulting.
Source
Thrown at src/expr/core/src/window_function/range.rs:236
/// It's very similar to `first_curr_of`, just with everything on the other direction.
pub fn last_curr_of(&self, order_value: impl ToOwnedDatum) -> Sentinelled<Datum> {
self.start
.for_calc()
.reverse()
.bound_of(order_value, self.order_type)
}
}
pub type RangeFrameBound = FrameBound<RangeFrameOffset>;
impl RangeFrameBound {
fn from_protobuf(
bound: &PbRangeFrameBound,
order_data_type: &DataType,
offset_data_type: &DataType,
) -> Result<Self> {
let bound = match bound.get_type()? {
PbBoundType::Unspecified => bail!("unspecified type of `RangeFrameBound`"),
PbBoundType::UnboundedPreceding => Self::UnboundedPreceding,
PbBoundType::CurrentRow => Self::CurrentRow,
PbBoundType::UnboundedFollowing => Self::UnboundedFollowing,
bound_type @ (PbBoundType::Preceding | PbBoundType::Following) => {
let offset_value = Datum::from_protobuf(bound.get_offset()?, offset_data_type)
.context("offset `Datum` is not decodable")?
.context("offset of `RangeFrameBound` must be non-NULL")?;
let mut offset = RangeFrameOffset::new(offset_value);
offset.prepare(order_data_type, offset_data_type)?;
if bound_type == PbBoundType::Preceding {
Self::Preceding(offset)
} else {
Self::Following(offset)
}
}
};
Ok(bound)
}View on GitHub (pinned to 6469eb736d)
Solutions
- Set the bound type explicitly in the frontend when constructing PbRangeFrameBound.
- Ensure the plan producer fills every frame bound's type before serialization.
- Inspect the serialized plan for unset oneof fields in frame bounds.
Example fix
// before bound.set_type(PbBoundType::Unspecified); // after bound.set_type(PbBoundType::Preceding);
Defensive patterns
Strategy: validation
Validate before calling
fn bound_type_is_set(b: &PbRangeFrameBound) -> bool { b.get_type().map(|t| !matches!(t, PbBoundType::Unspecified)).unwrap_or(false) } Type guard
fn is_specified_bound(t: PbBoundType) -> bool { !matches!(t, PbBoundType::Unspecified) } Try / catch
let bound = match RangeFrameBound::from_protobuf(&pb_bound, &order_type, &offset_type) {
Ok(b) => b,
Err(e) => return Err(e.context("malformed RANGE frame bound in plan")),
}; Prevention
- Always set the bound type oneof when building PbRangeFrameBound.
- Default UnboundedPreceding/CurrentRow explicitly in the binder.
- Add proto round-trip tests for frame bounds.
When it happens
Trigger: Deserializing a PbRangeFrameBound whose get_type() returns Unspecified — the bound type field was not set in the protobuf plan message.
Common situations: Frontend omitted the bound type when building the WindowFunction proto, an older protocol version, or hand-crafted test protobufs.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unspecified type of `FrameExclusion`
- Unspecified window function type
- unspecified type of `WindowFrame`
- no such window function type
- unspecified type of `RowsFrameBound`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/e708f0bf7f839e98.
Report an issue: GitHub.