risingwavelabs/risingwave · error · MemTableError
Inconsistent operation on table
Error message
Inconsistent operation on table {table_id} {key:?}, prev: {prev:?}, new: {new:?} What it means
A MemTable received a KeyOp that is inconsistent with the operation already recorded for the same key (e.g. inserting a key that was previously deleted, or conflicting delete/insert sequences). This enforces per-key operation consistency in the shared buffer memtable.
Solutions
- Inspect the reported prev and new KeyOp values to understand the conflict
- Trace the writer producing the key ops (epoch, actor/task id) for a logic bug
- Verify the upstream source or MV definition is not re-emitting conflicting ops for the same key
- If triggered by malformed user data, validate/normalize input before writing
Defensive patterns
Strategy: try-catch
Try / catch
match memtable.write(...).await {
Err(e) if matches!(e.as_ref(), MemTableError::InconsistentOperation { .. }) => {
tracing::error!(error = ?e, "conflicting key op");
// surface as data-corruption / trigger recovery
}
other => other?,
} Prevention
- Ensure upstream operators emit at most one consistent op per key per epoch
- Validate/replay input streams deterministically in tests
- Track tombstones so deletes are respected before re-inserts
When it happens
Trigger: Writing to a table where the same key already has a conflicting KeyOp (prev vs new), detected in MemTable::write under OpConsistencyLevel checks.
Common situations: Bugs in stream/batch write paths that replay or interleave operations incorrectly, upstream executor bugs re-writing tombstoned keys, or corrupted input data causing out-of-order operations.
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
- Committed epoch mismatch: table
- MemTable error
- SharedBuffer error
- BackupStorage error
- Barrier read is unavailable for now. Likely the cluster is…
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/5a4180b8b473f6d5.
Report an issue: GitHub.
Appendix: source
Thrown at src/storage/src/mem_table.rs:56
pub enum KeyOp {
Insert(Bytes),
Delete(Bytes),
/// (`old_value`, `new_value`)
Update((Bytes, Bytes)),
}
/// `MemTable` is a buffer for modify operations without encoding
#[derive(Clone)]
pub struct MemTable {
table_id: TableId,
pub(crate) buffer: MemTableStore,
pub(crate) op_consistency_level: OpConsistencyLevel,
pub(crate) kv_size: KvSize,
}
#[derive(Error, Debug)]
pub enum MemTableError {
#[error("Inconsistent operation on table {table_id} {key:?}, prev: {prev:?}, new: {new:?}")]
InconsistentOperation {
table_id: TableId,
key: TableKey<Bytes>,
prev: KeyOp,
new: KeyOp,
},
}
type Result<T> = std::result::Result<T, Box<MemTableError>>;
pub type MemTableStore = BTreeMap<TableKey<Bytes>, KeyOp>;
pub struct MemTableIteratorBuilder;
pub struct MemTableRevIteratorBuilder;
fn map_to_hummock_value<'a>(
(key, op): (&'a TableKey<Bytes>, &'a KeyOp),
) -> (TableKey<&'a [u8]>, HummockValue<&'a [u8]>) {
(View on GitHub (pinned to 6469eb736d)