risingwavelabs/risingwave · critical

job {} in database {} has tables with different table ids. {

Error message

job {} in database {} has tables with different table ids. {}:{}, {}:{}

What it means

validate_database_info requires all state tables of a streaming job to share the same committed epoch, ensuring the job's tables are consistent at a single recovery point. If a table's epoch differs from the first table's epoch, recovery aborts with this error listing both (table, epoch) pairs. Note: the message says 'different table ids' but the values compared are epochs — a message wording quirk.

Source

Thrown at src/meta/src/barrier/mod.rs:209

                let mut committed_epochs =
                    InflightFragmentInfo::existing_table_ids(fragments.values()).map(|table_id| {
                        (
                            table_id,
                            *state_table_committed_epochs
                                .get(&table_id)
                                .expect("checked exist"),
                        )
                    });
                let (first_table, first_epoch) = committed_epochs.next().ok_or_else(|| {
                    anyhow!(
                        "job {} in database {} has no state table after recovery",
                        job_id,
                        database_id
                    )
                })?;
                for (table_id, epoch) in committed_epochs {
                    if epoch != first_epoch {
                        return Err(anyhow!(
                            "job {} in database {} has tables with different table ids. {}:{}, {}:{}",
                            job_id,
                            database_id,
                            first_table,
                            first_epoch,
                            table_id,
                            epoch
                        )
                        .into());
                    }
                }
            }
        }
        Ok(())
    }
}

#[derive(Debug)]

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Retry recovery from a consistent Hummock version snapshot where all tables share one epoch
  2. Investigate barrier commit logs to find where table epochs diverged and repair metadata
  3. Rebuild the affected job (recreate the MV/sink) if its table epochs cannot be reconciled
  4. File a bug; cross-table epoch atomicity should be guaranteed by barrier commits
Defensive patterns

Strategy: try-catch

Validate before calling

let epochs: HashSet<_> = job.state_tables()
    .map(|(t, e)| e)
    .collect();
if epochs.len() > 1 { return Err("state tables at divergent epochs; recovery would be inconsistent"); }

Try / catch

match validate_database_info(...) {
    Err(e) if e.to_string().contains("different table ids") => {
        restore_consistent_hummock_snapshot().await; // roll back to a single-epoch version
        retry_recovery().await;
    }
    r => r,
}

Prevention

When it happens

Trigger: Recovery where job state tables were committed at different epochs — e.g. some tables advanced in a barrier while others did not, indicating a partially-committed barrier or inconsistent Hummock version pinning.

Common situations: Crash/failover mid-barrier leaving tables at divergent epochs; bugs in barrier commit atomicity across state tables; restored version checkpoints that are partially applied.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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