risingwavelabs/risingwave · error
unspecified type of `WindowFrame`
Error message
unspecified type of `WindowFrame`
What it means
`Frame::from_protobuf` deserializes a window frame from its protobuf representation. The protobuf `Type` enum includes an `Unspecified` placeholder which is not a valid frame type, so it is explicitly rejected when building the frame.
Source
Thrown at src/expr/core/src/window_function/call.rs:93
}
pub fn rows_with_exclusion(
start: RowsFrameBound,
end: RowsFrameBound,
exclusion: FrameExclusion,
) -> Self {
Self {
bounds: FrameBounds::Rows(RowsFrameBounds { start, end }),
exclusion,
}
}
}
impl Frame {
pub fn from_protobuf(frame: &PbWindowFrame) -> Result<Self> {
use risingwave_pb::expr::window_frame::PbType;
let bounds = match frame.get_type()? {
PbType::Unspecified => bail!("unspecified type of `WindowFrame`"),
#[expect(deprecated)]
PbType::RowsLegacy => {
#[expect(deprecated)]
{
let start = FrameBound::<usize>::from_protobuf_legacy(frame.get_start()?)?;
let end = FrameBound::<usize>::from_protobuf_legacy(frame.get_end()?)?;
FrameBounds::Rows(RowsFrameBounds { start, end })
}
}
PbType::Rows => {
let bounds = must_match!(frame.get_bounds()?, PbBounds::Rows(bounds) => bounds);
FrameBounds::Rows(RowsFrameBounds::from_protobuf(bounds)?)
}
PbType::Range => {
let bounds = must_match!(frame.get_bounds()?, PbBounds::Range(bounds) => bounds);
FrameBounds::Range(RangeFrameBounds::from_protobuf(bounds)?)
}
PbType::Session => {View on GitHub (pinned to 6469eb736d)
Solutions
- Ensure the frontend always sets `WindowFrame.type` (Rows/Range/Groups) when building `PbWindowFrame`.
- Check for version skew between frontend and compute nodes and redeploy with matching versions.
- If you construct plan protobufs in tests/tools, populate the frame type field explicitly.
Example fix
// before
let frame = PbWindowFrame { start: Some(start), end: Some(end), ..Default::default() }; // type Unspecified
// after
let frame = PbWindowFrame {
start: Some(start),
end: Some(end),
r#type: PbType::Rows as i32,
..Default::default()
}; Defensive patterns
Strategy: validation
Validate before calling
# protobuf producer side (Rust pseudo) assert_ne!(frame.get_type().unwrap(), PbType::Unspecified, "frame type must be set");
Type guard
fn frame_type_is_set(f: &PbWindowFrame) -> bool { f.r#type != PbType::Unspecified as i32 } Try / catch
match Frame::from_protobuf(&pb_frame) {
Ok(frame) => frame,
Err(e) if e.to_string().contains("unspecified type") => bail!("plan corruption: WindowFrame type missing"),
Err(e) => return Err(e.into()),
} Prevention
- Always set `r#type` when constructing PbWindowFrame
- Keep frontend and compute node versions aligned
- Add round-trip serialization tests for WindowFrame
When it happens
Trigger: A `PbWindowFrame` message with `type: Unspecified` is passed to `Frame::from_protobuf` — typically when a plan fragment serialized by a frontend lacking frame-type info (or a version-mismatched frontend) is deserialized by the stream/batch engine.
Common situations: Mixed-version deployment where an older frontend omits the frame type; a hand-crafted or corrupted plan protobuf; a frontend bug that fails to set Rows/RowsLegacy/Range/Groups before serialization.
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
- Failed to decode prost: field not found `{}`
- unspecified type of `FrameExclusion`
- Unspecified window function type
- unspecified type of `RangeFrameBound`
- offset of `RowsFrameBound` must be `Integer`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/9bec33a34b783450.
Report an issue: GitHub.