clockworklabs/SpacetimeDB · error
ChangeTableAccessorName: `{table_name}` not found in new mod
Error message
ChangeTableAccessorName: `{table_name}` not found in new module def What it means
SpacetimeDB throws this while applying an AutoMigrateStep::ChangeTableAccessorName step of an auto-migration plan: the planner decided a table's accessor name (the module-side alias, e.g. the Rust table type name) changed, but plan.new.find_table((namespace, local)) returns None, so the new alias cannot be read. The migration plan and the module definitions it was generated from are out of sync: the step's table key no longer resolves in the new module def. The publish/update transaction aborts before any mutation is applied for this step.
Source
Thrown at crates/engine/src/update.rs:373
let stored_name = namespace.join_raw(&index_name.clone().into());
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 index_schema = table_schema
.indexes
.iter()
.find(|index| index.index_name == stored_name)
.ok_or_else(|| anyhow::anyhow!("Index `{index_name}` not found in table `{table_full_name}`"))?;
log!(logger, "Dropping index `{index_name}` on table `{table_full_name}`");
stdb.drop_index(tx, index_schema.index_id)?;
}
spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeTableAccessorName(table_name_key) => {
let (namespace, local) = table_name_key;
let table_name = joined(namespace, local);
let (_, new_table_def): (&ModuleDef, &spacetimedb_schema::def::TableDef) =
plan.new.find_table(table_name_key).ok_or_else(|| {
anyhow::anyhow!("ChangeTableAccessorName: `{table_name}` not found in new module def")
})?;
let table_id = stdb.table_id_from_name_mut(tx, &table_name)?.unwrap();
let new_alias = namespace.join(new_table_def.accessor_name.clone());
log!(
logger,
"Changing table accessor name for `{table_name}` to `{new_alias}`",
);
stdb.alter_table_accessor_name(tx, table_id, new_alias)?;
}
spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeColumnAccessorName(table_name_key, col_name) => {
let (namespace, local) = table_name_key;
let table_name = joined(namespace, local);
let (_, new_table_def): (&ModuleDef, &spacetimedb_schema::def::TableDef) =
plan.new.find_table(table_name_key).ok_or_else(|| {
anyhow::anyhow!("ChangeColumnAccessorName: `{table_name}` not found in new module def")
})?;View on GitHub (pinned to 6dee26c6ef)
Solutions
- Clean-rebuild the module and republish: cargo clean -p <module-crate> (or delete target/), then spacetime build && spacetime publish <db> - removes stale artifacts that desync the plan from the defs.
- Split the change into two publishes: first publish the pure accessor rename (stored table name and module path unchanged), then publish the rename/move of the table.
- Pin the stored name with #[spacetimedb::table(name = "...")] so accessor renames never change the (namespace, local) key the planner uses.
- Verify the SDK, CLI, and server versions used now match the versions that produced the live database; align them in Cargo.toml and CI.
- For disposable/dev databases: spacetime publish --delete-data <db> (alias --clear-database) to recreate the schema from scratch and skip auto-migration.
- If it reproduces on a clean build with matching versions, capture the module source and open a SpacetimeDB issue - this is an auto_migrate planner invariant violation.
Example fix
// before: one publish combines accessor rename with rename + move to submodule
mod guild {
#[spacetimedb::table(name = "members")] // was top-level `players`
pub struct Member {} // type was `Player`
}
// after: two publishes, stored name pinned
// publish 1: accessor rename only, same stored name and location
#[spacetimedb::table(name = "players")]
pub struct Member {}
// publish 2 (separate): rename/move the table
mod guild {
#[spacetimedb::table(name = "members")]
pub struct Member {}
} Defensive patterns
Strategy: validation
Validate before calling
use spacetimedb_schema::auto_migrate::AutoMigrateStep;
// Before applying an auto-migrate plan, verify every step resolves in the new def.
for step in &plan.steps {
if let AutoMigrateStep::ChangeTableAccessorName(key) = step {
if plan.new.find_table(key).is_none() {
anyhow::bail!("plan step references table {:?} missing from new module def", key);
}
}
} Type guard
fn table_resolves_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("ChangeTableAccessorName")
&& e.to_string().contains("not found in new module def") => {
// Plan/def desync: fall back to split publishes or, on dev DBs, --delete-data.
}
result => result?,
} Prevention
- Pin table names with #[table(name = "...")] so refactors never change the planner's key.
- Publish one logical schema change at a time; never combine accessor renames with renames, moves, or deletions.
- Keep SDK, CLI, and server versions locked across all machines and CI that publish the same database.
- Clean-build the module before publishing after any toolchain upgrade.
When it happens
Trigger: A publish where the table's accessor changed (Rust type renamed) while the table was also renamed, moved to a different submodule (changing its namespace key), or deleted in the same build; or stale build artifacts / a different spacetimedb compiler or SDK version producing a new module def that differs from the one the planner diffed in ponder_migrate.
Common situations: Refactors that rename table structs and simultaneously edit #[table(name = ...)] or reorganize modules into submodules; CI pipelines publishing with a different toolchain than the one that built the running database; switching spacetimedb-standalone or CLI versions between publishes.
Related errors
- ChangeColumnAccessorName: `{table_name}` not found in new mo
- ChangeColumns: table `{table_name}` not found in new module
- AddColumns: table `{table_name}` not found in new module def
- 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/37351f8b5e1e9c27.
Report an issue: GitHub.