clockworklabs/SpacetimeDB · error · anyhow::Error

Cannot remove table `{table_name}`: table contains data. Cle

Error message

Cannot remove table `{table_name}`: table contains data. Clear the table's rows (e.g. via a reducer) before removing it from your schema.

What it means

Thrown by the auto-migrator when a new module version removes a table that still contains rows. SpacetimeDB refuses to drop non-empty tables during an automatic migration because that would silently destroy live data, so the whole update transaction is aborted with anyhow::bail.

Source

Thrown at crates/engine/src/update.rs:274

                {
                    anyhow::bail!("Precheck failed: added sequence {sequence_name} already has values in range",);
                }
            }
        }
    }

    log::info!("Running database update steps: {}", stdb.database_identity());
    let mut res = UpdateResult::Success;

    for step in plan.steps {
        match step {
            spacetimedb_schema::auto_migrate::AutoMigrateStep::RemoveTable(table_name_key) => {
                let (namespace, local) = table_name_key;
                let table_name = joined(namespace, local);
                let table_id = stdb.table_id_from_name_mut(tx, &table_name)?.unwrap();

                if stdb.table_row_count_mut(tx, table_id).unwrap_or(0) > 0 {
                    anyhow::bail!(
                        "Cannot remove table `{table_name}`: table contains data. \
                         Clear the table's rows (e.g. via a reducer) before removing it from your schema."
                    );
                }

                log!(logger, "Dropping table `{table_name}`");
                stdb.drop_table(tx, table_id)?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::AddTable(table_name_key) => {
                let (namespace, local) = table_name_key;
                let table_name = joined(namespace, local);
                let (owning_def, table_def) = plan
                    .new
                    .find_table(table_name_key)
                    .ok_or_else(|| anyhow::anyhow!("AddTable: table `{table_name}` not found in new module def"))?;
                log!(logger, "Creating table `{table_name}`");
                create_table_from_def_with_prefix(stdb, tx, owning_def, table_def, namespace)?;
            }

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Clear the table's rows before publishing, e.g. spacetime sql <db> "DELETE FROM <table>", or call a cleanup reducer that deletes all rows.
  2. If the data is disposable, delete and republish the database (spacetime delete <db> && spacetime publish <db>) so the table never exists at publish time.
  3. Keep the table in the schema for one more publish cycle and remove it only after confirming it is empty.
  4. Use the manual migration tooling (spacetime migrate) to author an explicit data-preserving migration instead of relying on auto-migrate.

Example fix

-- before: publish removes table, rows still present -> error
spacetime publish my-db

-- after: clear rows first, then publish
spacetime sql my-db "DELETE FROM old_table"
spacetime publish my-db
Defensive patterns

Strategy: validation

Validate before calling

-- before publishing a version that removes a table:
spacetime sql my-db "SELECT COUNT(*) AS n FROM old_table"
-- if n > 0, clear it first:
spacetime sql my-db "DELETE FROM old_table"

Try / catch

match publish(&db, &module).await {
    Err(e) if e.to_string().contains("table contains data") => {
        // clear rows via reducer/SQL, then retry the publish once
    }
    other => other,
}

Prevention

When it happens

Trigger: Publishing a module whose schema no longer declares a table that exists in the database, while stdb.table_row_count_mut(tx, table_id) returns > 0 for that table in the AutoMigrateStep::RemoveTable branch of the update plan.

Common situations: Renaming a table (old table dropped, new one added) on a database with data; cleaning up 'unused' tables that actually hold rows; iterating on schemas against a dev database that accumulated test data instead of being republished fresh.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/130f3d2a2ed51b80. Report an issue: GitHub.