clockworklabs/SpacetimeDB · error

`CommittedState::replay_columns_to_ignore` should be empty a

Error message

`CommittedState::replay_columns_to_ignore` should be empty at the end of a commit, but found {} entries

What it means

replay_end_tx is the commit boundary of CommittedState replay: every st_column row parked in replay_columns_to_ignore (superseded column versions awaiting their outdated markers) must have been consumed during the transaction. A non-empty set means a column-schema update started but never completed, so replay ends in an inconsistent state and fails instead of guessing.

Source

Thrown at crates/datastore/src/locking_tx_datastore/replay.rs:1056

            return Ok(());
        }

        // Get the table for mutation.
        let (table, blob_store, ..) = self.get_table_and_blob_store_mut(table_id)?;

        // We do not need to consider a truncation of `st_table` itself,
        // as if that happens, the database is bricked.

        table.clear(blob_store);

        Ok(())
    }

    fn replay_end_tx(&mut self) -> Result<()> {
        self.next_tx_offset += 1;

        if !self.replay_columns_to_ignore.is_empty() {
            return Err(anyhow::anyhow!(
                "`CommittedState::replay_columns_to_ignore` should be empty at the end of a commit, but found {} entries",
                self.replay_columns_to_ignore.len(),
            ).into());
        }

        if !self.replay_table_updated.is_empty() {
            return Err(anyhow::anyhow!(
                "`CommittedState::replay_table_updated` should be empty at the end of a commit, but found {} entries",
                self.replay_table_updated.len(),
            )
            .into());
        }

        // Any dropped tables should be fully gone by the end of a transaction;
        // if we see any reference to them in the future we should error, not ignore.
        self.replay_table_dropped.clear();

        Ok(())

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Restore from a snapshot predating the broken transaction
  2. Replay with the version that wrote the schema change
  3. Report the invariant violation to spacetimedb maintainers together with the commitlog — likely a replay bug, not user error
Defensive patterns

Strategy: fallback

Try / catch

Catch at open, include the entry count from the message in the incident report, restore from a pre-migration snapshot, and file a spacetimedb bug with the commitlog — this is an internal invariant, not caller error.

Prevention

When it happens

Trigger: A commitlog transaction that interleaves st_column updates abnormally (e.g. add + drop column sequences that never emit the expected follow-up rows); a truncated log cutting a schema change in half; a bug in the replay bookkeeping that fails to drain the set.

Common situations: Crash during a schema migration commit; replaying logs written by a different spacetimedb version; fuzzed or hand-crafted commitlogs in testing.

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 clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/f8810b532a989093. Report an issue: GitHub.