clockworklabs/SpacetimeDB · error
ChangeColumns: table `{table_name}` not found in new module
Error message
ChangeColumns: table `{table_name}` not found in new module def What it means
Applying AutoMigrateStep::ChangeColumns, which replaces a table's row type after column additions/removals/type changes: plan.new.find_table fails, so the replacement column schemas cannot be built. The step's table key does not resolve in the new module def - plan/def desync. The publish aborts before alter_table_row_type runs.
Source
Thrown at crates/engine/src/update.rs:545
let table_id = stdb.table_id_from_name_mut(tx, &table_full_name)?.unwrap();
let table_schema = stdb.schema_for_table_mut(tx, table_id)?;
let sequence_schema = table_schema
.sequences
.iter()
.find(|sequence| sequence.sequence_name == stored_name)
.unwrap();
log!(
logger,
"Dropping sequence `{sequence_name}` from table `{table_full_name}`"
);
stdb.drop_sequence(tx, sequence_schema.sequence_id)?;
}
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);View on GitHub (pinned to 6dee26c6ef)
Solutions
- Clean-rebuild and republish.
- Split the publish: apply column changes with the table name/location untouched first, then rename/move.
- Pin the stored name with #[table(name = "...")] and keep it stable across the migration.
- Align SDK/CLI/server versions with the live database's provenance.
- Dev: spacetime publish --delete-data <db>.
- Report as a planner bug if a clean split publish still triggers it.
Example fix
// before: rename + column add in one publish
#[spacetimedb::table(name = "members")] // was "players"
pub struct Member { pub level: u32 /* new column */ }
// after: two publishes
// 1) add the column, keep the name
#[spacetimedb::table(name = "players")]
pub 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::ChangeColumns(key) = step {
if plan.new.find_table(key).is_none() {
anyhow::bail!("ChangeColumns 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("ChangeColumns")
&& e.to_string().contains("not found in new module def") => {
// Split: publish column changes with a stable table name; rename afterwards.
}
result => result?,
} Prevention
- Never mix column type/add/drop changes with table renames in one publish.
- Pin table names with #[table(name = "...")] before evolving columns.
- Clean-build before publishing after toolchain changes.
- One logical schema change per publish.
When it happens
Trigger: Changing a table's columns (types, adds, drops) 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: Squashed feature branches combining column changes with table renames; CI publishing with a different toolchain; incremental builds after SDK upgrades.
Related errors
- ChangeTableAccessorName: `{table_name}` not found in new mod
- AddColumns: table `{table_name}` not found in new module def
- ChangeColumnAccessorName: `{table_name}` not found in new mo
- Column `{col_name}` not found in table `{table_name}`
- ChangeIndexSourceName: `{index_name}` not found in old modul
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/e25f79fb1fdd90cf.
Report an issue: GitHub.