risingwavelabs/risingwave · error
new item epoch {} does not match current chunk offset epoch
Error message
new item epoch {} does not match current chunk offset epoch {} What it means
`check_next_item_epoch` on a `TruncateOffset::Chunk` requires that any new item written to the log store carries exactly the same epoch as the current chunk offset epoch. A mismatch means an item from a different epoch is being appended into a chunk opened for another epoch.
Source
Thrown at src/connector/src/sink/log_store.rs:96
if *self >= next_offset {
bail!(
"next offset {:?} should be later than current offset {:?}",
next_offset,
self
)
} else {
Ok(())
}
}
pub fn check_next_item_epoch(&self, epoch: u64) -> LogStoreResult<()> {
match self {
TruncateOffset::Chunk {
epoch: offset_epoch,
..
} => {
if epoch != *offset_epoch {
bail!(
"new item epoch {} does not match current chunk offset epoch {}",
epoch,
offset_epoch
);
}
}
TruncateOffset::Barrier {
epoch: offset_epoch,
} => {
if epoch <= *offset_epoch {
bail!(
"new item epoch {} does not exceed barrier offset epoch {}",
epoch,
offset_epoch
);
}
}
}View on GitHub (pinned to 6469eb736d)
Solutions
- Close/rotate the current chunk and advance the offset when the item's epoch differs from the chunk epoch
- Verify the item's epoch is stamped from the same source as the chunk epoch
- Check barrier handling so epoch transitions always precede new items
Example fix
// before
store.check_next_item_epoch(new_epoch); // chunk opened with old_epoch
// after
if new_epoch != chunk_epoch {
store.flush_chunk_and_advance(new_epoch);
}
store.check_next_item_epoch(new_epoch); Defensive patterns
Strategy: validation
Validate before calling
assert_eq!(item_epoch, chunk_epoch, "item epoch must match open chunk epoch");
Type guard
fn matches_chunk_epoch(epoch: u64, offset: &TruncateOffset) -> bool {
matches!(offset, TruncateOffset::Chunk { epoch: e, .. } if *e == epoch)
} Try / catch
match offset.check_next_item_epoch(epoch) {
Err(e) => { store.rotate_chunk(epoch)?; store.check_next_item_epoch(epoch)?; }
Ok(()) => {}
} Prevention
- Rotate the chunk whenever the item epoch changes
- Derive item epochs and chunk epochs from the same barrier stream
- Test epoch-transition paths in sink writers
When it happens
Trigger: Calling `check_next_item_epoch(epoch)` while the current offset is `TruncateOffset::Chunk { epoch: offset_epoch, .. }` and `epoch != offset_epoch`; typically when a sink item's epoch changed mid-chunk without closing the chunk first.
Common situations: Sink writers mixing items from adjacent epochs; barrier handling that fails to flush/rotate the chunk before the epoch advances.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- new item epoch {} does not exceed barrier offset epoch {}
- next offset {:?} should be later than current offset {:?}
- Division by zero
- Array error: {0}
- file_scan function is not supported in streaming mode
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/a8e2a85db2b5a05d.
Report an issue: GitHub.