risingwavelabs/risingwave · error · ExprError::Internal
expected DenseRankState, got {other:?}
Error message
expected DenseRankState, got {other:?} What it means
`DenseRank` window function state is deserialized only from `FunctionState::DenseRankState`. Any other variant means the persisted state does not belong to this function and deserialization fails with this internal error.
Source
Thrown at src/expr/impl/src/window_function/rank.rs:174
self.prev_order_key = Some(curr_key.order_key);
self.prev_rank = curr_rank;
curr_rank
}
fn to_proto_state(&self) -> FunctionState {
FunctionState::DenseRankState(DenseRankState {
prev_order_key: self.prev_order_key.as_ref().map(|k| k.to_vec()),
prev_rank: self.prev_rank,
})
}
fn from_proto_state(state: FunctionState) -> Result<Self> {
match state {
FunctionState::DenseRankState(s) => Ok(Self {
prev_order_key: s.prev_order_key.map(Into::into),
prev_rank: s.prev_rank,
}),
other => Err(ExprError::Internal(anyhow::anyhow!(
"expected DenseRankState, got {other:?}"
))),
}
}
}
/// Generic state for rank window functions including `row_number`, `rank` and `dense_rank`.
#[derive(EstimateSize)]
pub(super) struct RankState<RF: RankFuncCount> {
/// First state key of the partition.
first_key: Option<StateKey>,
/// State keys that are waiting to be outputted.
buffer: EstimatedVecDeque<StateKey>,
/// Function-specific state.
func_state: RF,
/// Whether persistence is enabled for this state.
persistence_enabled: bool,
/// The key of the last output row (for snapshot).View on GitHub (pinned to 6469eb736d)
Solutions
- Recreate / full-rebuild the materialized view so state matches the function kind
- Verify state keys are not shared between different window functions
- Check RisingWave version consistency across the cluster when restoring state
Example fix
// before
other => Err(ExprError::Internal(anyhow::anyhow!("expected DenseRankState, got {other:?}"))),
// after
// ensure plan and state agree: use FunctionState::DenseRankState when writing state for DENSE_RANK Defensive patterns
Strategy: try-catch
Validate before calling
fn state_matches(state: &FunctionState) -> bool { matches!(state, FunctionState::DenseRankState(_)) } Type guard
fn as_dense_rank_state(s: &FunctionState) -> Option<&DenseRankState> { match s { FunctionState::DenseRankState(x) => Some(x), _ => None } } Try / catch
match DenseRank::from_proto_state(state) {
Err(e) if e.to_string().contains("expected DenseRankState") => rebuild_mv_state(),
other => other?,
} Prevention
- Do not swap RANK/DENSE_RANK in place; recreate the object
- Keep RisingWave versions consistent when restoring checkpoints
- Test recovery of window aggregates after plan changes
When it happens
Trigger: `DenseRank::from_proto_state` receiving a different FunctionState variant — mismatch between the function kind and the stored state, typically during stream recovery or after changing the window function definition.
Common situations: Altering a materialized view from RANK to DENSE_RANK without rebuild; state corruption or version skew between nodes.
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 RankState, 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/ae5b32788a88817a.
Report an issue: GitHub.