risingwavelabs/risingwave · error
corrupt MATCH_RECOGNIZE state row: seq column must be a non-
Error message
corrupt MATCH_RECOGNIZE state row: seq column must be a non-null int64, got {other:?} What it means
MATCH_RECOGNIZE persists its pattern-matching state rows in a `[seq, <input columns>]` layout, where the first column is a monotonically increasing int64 sequence number. During state recovery the executor reads that column and throws this error if it is null or any type other than Int64. It is deliberately a descriptive error instead of a panic because a panic would crash-loop recovery forever on state that recovery cannot repair.
Source
Thrown at src/stream/src/executor/match_recognize/executor.rs:1104
.iter_keyed_row_with_vnode(
vnode,
&(
std::ops::Bound::<OwnedRow>::Unbounded,
std::ops::Bound::<OwnedRow>::Unbounded,
),
Default::default(),
)
.await?;
pin_mut!(stream);
while let Some(kv) = stream.next().await {
let kv = kv?;
let stored = kv.row();
// Stored layout: `[ seq, <input cols..> ]`. Fail descriptive on a corrupt row —
// a panic here would crash-loop recovery on state that recovery cannot fix.
let seq = match stored.datum_at(0) {
Some(ScalarRefImpl::Int64(s)) => s,
other => {
return Err(anyhow::anyhow!(
"corrupt MATCH_RECOGNIZE state row: seq column must be a non-null \
int64, got {other:?}"
)
.into());
}
};
max_seq = max_seq.max(seq);
let input_row = OwnedRow::new(
(1..stored.len())
.map(|i| stored.datum_at(i).to_owned_datum())
.collect(),
);
let pk = (&input_row).project(partition_key_indices).into_owned_row();
let order_key = input_row.datum_at(time_col).to_owned_datum();
// Not counted here: the ingest path counted this row once already, and a rebuild
// re-evaluates every retained row on each recovery.
let deadline = eval_deadline(within_deadline, &order_key).await;
let run = parts.entry(pk).or_insert_with(|| PartitionRun {View on GitHub (pinned to 6469eb736d)
Solutions
- Drop and recreate the MATCH_RECOGNIZE materialization/table so state is rebuilt from scratch, since recovery cannot fix a corrupt row
- Check whether the cluster was restored from a backup made by an incompatible RisingWave version; restore from a backup made by the same version instead
- Inspect the offending state row (the error logs `got {other:?}`) to confirm null vs wrong-type, and look for corresponding storage/Hummock corruption reports
- File an issue with RisingWave including the full error and the actor/state-table id; this is an internal invariant failure, not user-fixable data
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
// Before recovery, sanity-check the state row's seq column
fn validate_seq_column(row: &[Datum]) -> Result<(), String> {
match row.first() {
Some(Some(ScalarImpl::Int64(_))) => Ok(()),
other => Err(format!("MATCH_RECOGNIZE state seq column invalid: {other:?}")),
}
} Type guard
fn is_valid_seq(d: &Datum) -> bool {
matches!(d, Some(ScalarImpl::Int64(_)))
} Try / catch
match executor_result {
Err(e) if e.to_string().contains("corrupt MATCH_RECOGNIZE state row") => {
// Recovery cannot repair this state: drop and recreate the table/job
recreate_match_recognize_job();
}
other => other?,
} Prevention
- Never restore state snapshots across RisingWave versions without a supported migration path
- Do not manually edit internal state tables
- Monitor for prior storage/Hummock errors that may have corrupted rows
- Test disaster-recovery restore procedures on MATCH_RECOGNIZE jobs in staging
When it happens
Trigger: State-table corruption or an incompatible schema version for the MATCH_RECOGNIZE state table: recovery reads a row whose column 0 is NULL, or was written by a different (older/newer) executor version that stored the sequence in another position/type, or manual state-table edits/restore produced a malformed row.
Common situations: Restoring a cluster from a snapshot/backup taken across a RisingWave version upgrade that changed the MATCH_RECOGNIZE state layout; interrupted state migrations; corrupted Hummock state due to storage-layer issues; users manually inspecting/mutating internal state tables.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid sign: {}
- Invalid row count state: {:?}
- legacy no-shuffle backfill recovered unfinished progress; ca
- intermediate state row has fewer columns ({}) than expected
- log_store_rewind_start_epoch {} not later than first_epoch {
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/55bdfc70d7fbb633.
Report an issue: GitHub.