risingwavelabs/risingwave · error · ExprError::Internal
expected RankState, got {other:?}
Error message
expected RankState, got {other:?} What it means
`Rank` window function state is deserialized from `FunctionState::RankState` only. Any other variant indicates the stored state belongs to a different window function, so deserialization fails with this internal error.
Source
Thrown at src/expr/impl/src/window_function/rank.rs:132
curr_rank
}
fn to_proto_state(&self) -> FunctionState {
FunctionState::RankState(RankStateProto {
prev_order_key: self.prev_order_key.as_ref().map(|k| k.to_vec()),
prev_rank: self.prev_rank,
prev_pos_in_peer_group: self.prev_pos_in_peer_group,
})
}
fn from_proto_state(state: FunctionState) -> Result<Self> {
match state {
FunctionState::RankState(s) => Ok(Self {
prev_order_key: s.prev_order_key.map(Into::into),
prev_rank: s.prev_rank,
prev_pos_in_peer_group: s.prev_pos_in_peer_group,
}),
other => Err(ExprError::Internal(anyhow::anyhow!(
"expected RankState, got {other:?}"
))),
}
}
}
#[derive(Default, EstimateSize)]
pub(super) struct DenseRank {
prev_order_key: Option<MemcmpEncoded>,
prev_rank: i64,
}
impl RankFuncCount for DenseRank {
fn count(&mut self, curr_key: StateKey) -> i64 {
let curr_rank = if let Some(prev_order_key) = self.prev_order_key.as_ref()
&& prev_order_key == &curr_key.order_key
{
// current key is in the same peer group as the previous oneView on GitHub (pinned to 6469eb736d)
Solutions
- Rebuild the materialized view to regenerate consistent state
- Confirm the state table used by this Rank function was not written by another function
- Audit FunctionState serialization/versioning for mismatches
Example fix
// before
other => Err(ExprError::Internal(anyhow::anyhow!("expected RankState, got {other:?}"))),
// after
// ensure the executor constructs the matching state type:
let state = FunctionState::RankState(RankState { .. }); // must match the function kind Defensive patterns
Strategy: try-catch
Validate before calling
fn state_matches(state: &FunctionState) -> bool { matches!(state, FunctionState::RankState(_)) } Type guard
fn as_rank_state(s: &FunctionState) -> Option<&RankState> { match s { FunctionState::RankState(x) => Some(x), _ => None } } Try / catch
match Rank::from_proto_state(state) {
Err(e) if e.to_string().contains("expected RankState") => rebuild_mv_state(),
other => other?,
} Prevention
- Rebuild materialized views after changing RANK to another window function
- Verify state tables after cluster restore
- Add assertions that the executor writes the matching FunctionState variant
When it happens
Trigger: `Rank::from_proto_state` called with e.g. DenseRankState or RowNumberState — mismatched function kind vs. persisted state, usually during recovery or after altering a window function in a materialized view.
Common situations: State-key collisions after plan changes; restoring checkpoints from a cluster running a different function set; migration between RisingWave versions.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- expected RowNumberState, got {other:?}
- expected DenseRankState, got {other:?}
- unspecified type of `WindowFrame`
- unspecified type of `FrameExclusion`
- Unspecified window function type
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/741856b77831dbd4.
Report an issue: GitHub.