clockworklabs/SpacetimeDB · error

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

Error message

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

What it means

Applying AddColumns, which adds columns to an existing table: plan.new.find_table fails, so neither the column schemas nor their default values can be built. The add-columns step references a table key absent from the new module def - plan/def desync. The publish aborts before any column is added.

Source

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

                log!(logger, "Adding row-level security `{sql_rls}`");
                let rls = plan.new.lookup::<RawRowLevelSecurityDefV9>(sql_rls).ok_or_else(|| {
                    anyhow::anyhow!("AddRowLevelSecurity: RLS `{sql_rls}` not found in new module def")
                })?;
                let rls = RowLevelExpr::build_row_level_expr(tx, &auth_ctx, rls)?;

                stdb.create_row_level_security(tx, rls.def)?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::RemoveRowLevelSecurity(sql_rls) => {
                log!(logger, "Removing row-level security `{sql_rls}`");
                stdb.drop_row_level_security(tx, sql_rls.clone())?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::AddColumns(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!("AddColumns: 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);

                let default_values: Vec<AlgebraicValue> = table_def
                    .columns
                    .iter()
                    .filter_map(|col_def| col_def.default_value.clone())
                    .collect();
                stdb.add_columns_to_table_mut_tx(tx, table_id, column_schemas, default_values)?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::DisconnectAllUsers => {
                log!(logger, "Disconnecting all users");
                // It does not disconnect clients right away,
                // but send response indicated that caller should drop clients
                res = UpdateResult::RequiresClientDisconnect;
            }
        }
    }

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Clean-rebuild and republish.
  2. Add the columns in their own publish with the table name and location unchanged.
  3. Pin the stored name with #[table(name = "...")] and keep it stable.
  4. Align SDK/CLI/server versions with the live database's provenance.
  5. Dev: spacetime publish --delete-data <db>.
  6. Report as a planner bug if a clean split publish still triggers it.

Example fix

// before: add a column AND rename the table in one publish
#[spacetimedb::table(name = "members")] // was `players`
pub struct Member { pub level: u32 /* new */ }

// after: two publishes
// 1) #[spacetimedb::table(name = "players")] struct Player { pub level: u32 }
// 2) rename the table separately
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

fn 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("AddColumns")
        && e.to_string().contains("not found in new module def") => {
        // Split: add columns with a stable table name; rename/move the table afterwards.
    }
    result => result?,
}

Prevention

When it happens

Trigger: Adding columns while renaming, moving, or deleting the table in the same publish; or the def set being applied differs from the one the planner diffed (stale build artifacts, mismatched compiler/SDK versions).

Common situations: Feature branches combining new fields with table renames; CI publishing with a different toolchain than the one that published the database; incremental builds after SDK upgrades.

Related errors


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