clockworklabs/SpacetimeDB · error
ChangeColumnAccessorName: `{table_name}` not found in new mo
Error message
ChangeColumnAccessorName: `{table_name}` not found in new module def What it means
Thrown while applying AutoMigrateStep::ChangeColumnAccessorName: the plan renames a column's accessor (the field alias used by module code) but plan.new.find_table((namespace, local)) fails, so the column list to search cannot even be obtained. The migration step's table key does not resolve in the new module definition the engine is applying against - plan and defs are inconsistent. The update aborts with no changes applied for this step.
Source
Thrown at crates/engine/src/update.rs:390
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")
})?;
let new_col_def = new_table_def
.columns
.iter()
.find(|col| &col.name == col_name)
.ok_or_else(|| anyhow::anyhow!("Column `{col_name}` not found in table `{table_name}`"))?;
let table_id = stdb.table_id_from_name_mut(tx, &table_name)?.unwrap();
let table_schema = stdb.schema_for_table_mut(tx, table_id)?;
let col_schema = table_schema
.columns
.iter()
.find(|col| &col.col_name == col_name)
.ok_or_else(|| anyhow::anyhow!("Column `{col_name}` not found in table `{table_name}`"))?;
log!(
logger,
"Changing column accessor name for `{}`.`{}` to `{}`",View on GitHub (pinned to 6dee26c6ef)
Solutions
- Clean-rebuild and republish: cargo clean -p <module-crate> (or remove target/), spacetime build, spacetime publish <db>.
- Split the publish: first change only the column accessor (table stored name and module path untouched), then apply the table rename/move in a second publish.
- Pin the table's stored name with #[spacetimedb::table(name = "...")] so the planner's (namespace, local) key stays stable across refactors.
- Make SDK, CLI, and server versions identical to those that published the live database.
- On dev databases: spacetime publish --delete-data <db> recreates the schema without auto-migration.
- Reproduces on clean builds? File a SpacetimeDB issue with the module diff - planner invariant violation.
Example fix
// before: one publish renames the column accessor AND moves the table
mod guild {
#[spacetimedb::table(name = "members")]
pub struct Member { pub life: u32 } // field was `hp`
}
// after: two publishes
// 1) accessor-only change, table untouched
#[spacetimedb::table(name = "players")]
pub struct Player { pub life: u32 } // was `hp`
// 2) then publish the table move separately Defensive patterns
Strategy: validation
Validate before calling
use spacetimedb_schema::auto_migrate::AutoMigrateStep;
for step in &plan.steps {
if let AutoMigrateStep::ChangeColumnAccessorName(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("ChangeColumnAccessorName")
&& e.to_string().contains("not found in new module def") => {
// Split the publish: accessor rename first, table rename/move later.
}
result => result?,
} Prevention
- Keep the table's stored name and module path stable when renaming column accessors.
- Pin names with #[table(name = ...)] and #[column(name = ...)].
- One logical schema change per publish.
- Delete target/ and rebuild after toolchain changes before publishing.
When it happens
Trigger: Publishing a build where a column accessor changed while its table was also renamed, moved to a submodule, or removed, so the table key no longer matches; or the new module def differs from what the planner diffed (stale target/ artifacts, mismatched compiler/SDK versions).
Common situations: Field renames bundled with table refactors; teams publishing the same database from machines with different spacetimedb toolchain versions; leftover target/ directories after toolchain upgrades.
Related errors
- ChangeTableAccessorName: `{table_name}` not found in new mod
- Column `{col_name}` not found in table `{table_name}`
- ChangeIndexSourceName: `{index_name}` not found in old modul
- ChangeIndexSourceName: `{index_name}` not found in new modul
- RemoveConstraint: `{constraint_name}` not found in old modul
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/96e4ac096f3de999.
Report an issue: GitHub.