risingwavelabs/risingwave · error · HummockError

Committed epoch mismatch: table {table_id}, committed_epoch

Error message

Committed epoch mismatch: table {table_id}, committed_epoch {committed_epoch}, read_epoch {read_epoch}

What it means

Hummock reports that the epoch a caller tried to read does not match the epoch that was actually committed for the table. Reads are pinned to a specific committed epoch; if the expected `committed_epoch` differs from the `read_epoch` being served, returning data would violate the versioned-snapshot guarantee, so the engine refuses. Created via `HummockError::committed_epoch_mismatch(table_id, committed_epoch, read_epoch)` in src/storage/src/hummock/error.rs:132.

Source

Thrown at src/storage/src/hummock/error.rs:55

    #[error("ObjectStore failed with IO error: {0}")]
    ObjectIoError(
        #[from]
        #[backtrace]
        ObjectError,
    ),
    #[error("Meta error: {0}")]
    MetaError(String),
    #[error("SharedBuffer error: {0}")]
    SharedBufferError(String),
    #[error("Wait epoch error: {0}")]
    WaitEpoch(String),
    #[error("Next epoch error: {0}")]
    NextEpoch(String),
    #[error("Change log retention miss: table {table_id}, epoch {epoch}")]
    ChangeLogRetentionMiss { table_id: TableId, epoch: u64 },
    #[error("Time-travel version expired: table {table_id}, epoch {epoch}")]
    TimeTravelVersionExpired { table_id: TableId, epoch: u64 },
    #[error(
        "Committed epoch mismatch: table {table_id}, committed_epoch {committed_epoch}, read_epoch {read_epoch}"
    )]
    CommittedEpochMismatch {
        table_id: TableId,
        committed_epoch: u64,
        read_epoch: u64,
    },
    #[error("Barrier read is unavailable for now. Likely the cluster is recovering")]
    ReadCurrentEpoch,
    #[error("CompactionExecutor error: {0}")]
    CompactionExecutor(String),
    #[error("FileCache error: {0}")]
    FileCache(String),
    #[error("SstObjectIdTracker error: {0}")]
    SstObjectIdTrackerError(String),
    #[error("CompactionGroup error: {0}")]
    CompactionGroupError(String),
    #[error("SstableUpload error: {0}")]

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Re-fetch a fresh current/read epoch from the Hummock version (e.g. via `ReadCurrentEpoch` semantics) and retry the read at the new epoch.
  2. Treat the read as aborted and re-execute the query/snapshot read; the epoch pin was stale, not the data.
  3. If it happens persistently for one table, check for barrier/DDL churn or failover issues around that table's commits.
  4. Enable tracing on `committed_epoch_mismatch` call sites to correlate with barriers and identify the race window.

Example fix

// before: propagating mismatch as fatal
let rows = read_at(read_epoch)?;
// after: re-pin to the current committed epoch and retry
let rows = match read_at(read_epoch) {
    Err(e) if matches!(e.inner(), HummockErrorInner::CommittedEpochMismatch { .. }) => {
        read_at(hummock.get_pinned_version().committed_epoch()?)?
    }
    other => other?,
};
Defensive patterns

Strategy: retry

Try / catch

match err.inner() {
    HummockErrorInner::CommittedEpochMismatch { table_id, committed_epoch, read_epoch } => {
        // stale epoch pin: re-pin to the current committed epoch and retry once
    }
    _ => return Err(err),
}

Prevention

When it happens

Trigger: A read or streaming read pinned to one epoch encounters a Hummock version whose committed epoch changed underneath it — e.g. a barrier advances/commits a new epoch between when the read epoch was chosen and when the data is fetched for `table_id`.

Common situations: Concurrent DDL/barriers racing with a batch or stream read; failover or cluster recovery rebuilding epoch state; a stale frontend/compute node reading with an epoch from before a recovery; retrying a request against a newly promoted leader with fresh epoch history.

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/805ec4db875af8b3. Report an issue: GitHub.