clockworklabs/SpacetimeDB · error

ReschemaEventTable: table `{table_name}` not found in new mo

Error message

ReschemaEventTable: table `{table_name}` not found in new module def

What it means

ReschemaEventTable rewrites the row type of a system event table (st_<table>_inserts/_deletes, e.g. backing scheduled tables) when the module's row type changes. plan.new.find_table fails, so the new column schemas cannot be derived - the step's table key does not resolve in the new module def. The publish aborts.

Source

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

            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeColumns(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!("ChangeColumns: table `{table_name}` not found in new module def")
                })?;
                let table_id = stdb.table_id_from_name_mut(tx, &table_name).unwrap().unwrap();
                let column_schemas = column_schemas_from_defs(owning_def, &table_def.columns, table_id);

                log!(logger, "Changing columns of table `{table_name}`");

                stdb.alter_table_row_type(tx, table_id, column_schemas)?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::ReschemaEventTable(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!("ReschemaEventTable: table `{table_name}` not found in new module def")
                })?;
                let table_id = stdb.table_id_from_name_mut(tx, &table_name).unwrap().unwrap();
                let column_schemas = column_schemas_from_defs(owning_def, &table_def.columns, table_id);

                log!(logger, "Changing schema of event table `{}`", table_name);

                stdb.alter_event_table_row_type(tx, table_id, column_schemas)?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeAccess(table_name_key) => {
                let (namespace, local) = table_name_key;
                let table_name = joined(namespace, local);
                let access = if let Some((_owning_def, table_def)) = plan.new.find_table(table_name_key) {
                    table_def.table_access
                } else {
                    let (_owning_def, view_def) = plan.new.find_view(table_name_key).ok_or_else(|| {
                        anyhow::anyhow!("ChangeAccess: `{table_name}` not found as a table or view in new module def")
                    })?;
                    if view_def.is_public {

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Clean-rebuild and republish.
  2. Change the scheduled table's fields in a dedicated publish with the table name/path unchanged.
  3. Keep scheduled table names pinned; rename them in separate publishes.
  4. Align toolchain versions before touching scheduled tables.
  5. Dev: spacetime publish --delete-data <db>.
  6. Report with the scheduled-table definition if it persists.

Example fix

// before: change a scheduled table's row type AND rename it in one publish
#[spacetimedb::table(name = "tick_new", scheduled(tick_old_reducer))]
pub struct TickNew { pub count: u64 }

// after: two publishes
// 1) add/modify columns keeping name `tick`
#[spacetimedb::table(name = "tick", scheduled(tick_reducer))]
pub struct Tick { pub count: u64 }
// 2) rename separately
Defensive patterns

Strategy: validation

Validate before calling

use spacetimedb_schema::auto_migrate::AutoMigrateStep;
for step in &plan.steps {
    if let AutoMigrateStep::ReschemaEventTable(key) = step {
        if plan.new.find_table(key).is_none() {
            anyhow::bail!("ReschemaEventTable step references table {:?} missing from new def", key);
        }
    }
}

Type guard

fn event_table_in_new_def(plan: &AutoMigratePlan, key: (&str, &str)) -> bool {
    plan.new.find_table(key).is_some()
}

Try / catch

match update_database(&stdb, tx, &plan, ...).await {
    Err(e) if e.to_string().contains("ReschemaEventTable") => {
        // Split: change the scheduled table's row type with its name untouched first.
    }
    result => result?,
}

Prevention

When it happens

Trigger: Changing a scheduled table's row type while renaming or moving it in the same publish; scheduler/event-table naming drift after compiler version changes; def/plan desync from stale artifacts.

Common situations: Editing fields of #[spacetimedb::table(scheduled = ...)] reducer tables together with renames; upgrading between spacetimedb versions that changed event-table naming.

Related errors


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