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

  1. Ensure the frontend always sets `WindowFrame.type` (Rows/Range/Groups) when building `PbWindowFrame`.
  2. Check for version skew between frontend and compute nodes and redeploy with matching versions.
  3. 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

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/9bec33a34b783450. Report an issue: GitHub.