clockworklabs/SpacetimeDB · critical · ReplayError
Error looking up name for truncated table {table_id:?}
Error message
Error looking up name for truncated table {table_id:?} What it means
While replaying the commitlog at database open, visit_truncate hit a TRUNCATE entry for a table whose schema is absent from committed state and whose name was not recorded in dropped_table_names. Without the st_table row there is no way to identify the table, so replay, and therefore database open, fails.
Source
Thrown at crates/datastore/src/locking_tx_datastore/replay.rs:362
// and therefore has performance implications and must not be disabled.
DB_METRICS
.rdb_num_table_rows
.with_label_values(self.database_identity, &table_id.into(), &table_name)
.dec();
Ok(row)
}
fn visit_truncate(&mut self, table_id: TableId) -> std::result::Result<(), Self::Error> {
let table_name = match self.committed_state.schema_for_table(table_id) {
// TODO: avoid clone
Ok(schema) => schema.table_name.clone(),
Err(_) => match self.dropped_table_names.remove(&table_id) {
Some(name) => name,
_ => {
return self
.process_error(anyhow!("Error looking up name for truncated table {table_id:?}").into());
}
},
};
if let Err(e) = self.committed_state.replay_truncate(table_id).with_context(|| {
format!(
"Error truncating table {:?} during transaction {:?} playback",
table_id, self.committed_state.next_tx_offset
)
}) {
self.process_error(e.into())?;
}
// NOTE: the `rdb_num_table_rows` metric is used by the query optimizer,
// and therefore has performance implications and must not be disabled.
DB_METRICS
.rdb_num_table_rows
.with_label_values(self.database_identity, &table_id.into(), &table_name)View on GitHub (pinned to 6dee26c6ef)
Solutions
- Restore the database from a clean snapshot/backup instead of replaying the damaged log
- Reopen with the exact spacetimedb version that wrote the commitlog, then re-upgrade
- If the data is disposable, recreate the database
- Preserve the commitlog and report the issue — truncate replay should not lose the st_table row
Defensive patterns
Strategy: fallback
Try / catch
Catch the error from RelationalDB::open / replay, classify it as commitlog corruption (look for the truncate-name-lookup message), then fall back to the most recent snapshot: restore it and replay only the post-snapshot segments. Surface a distinct 'database unrecoverable, snapshot restored' status to operators.
Prevention
- Take periodic snapshots so replay never starts from a damaged baseline
- Shut the database down gracefully before upgrades or disk moves
- Test the upgrade path on a copy of production data before switching over
- Keep writer and reader nodes on the same spacetimedb version
When it happens
Trigger: Replaying a commitlog in which the st_table row for a truncated table was dropped or never written in the order replay expects; a truncated or corrupted commitlog segment; a log produced by a spacetimedb version whose system-table write order differs.
Common situations: Reopening a data directory after a crash mid-schema-change (drop-then-truncate sequences); upgrading spacetimedb and replaying old logs; partially copied or restored database files.
Related errors
- Delete for non-existent row when replaying transaction
- When replaying `st_column` update: `table_type` should not h
- When replaying `st_column` update: `table_primary_key` shoul
- `CommittedState::replay_columns_to_ignore` should be empty a
- `CommittedState::replay_table_updated` should be empty at th
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/2da8e1a350731efa.
Report an issue: GitHub.