clockworklabs/SpacetimeDB · error
Column `{col_name}` not found in table `{table_name}`
Error message
Column `{col_name}` not found in table `{table_name}` What it means
During ChangeColumnAccessorName the engine found the table in the new module def but no column whose name equals the step's col_name (new_table_def.columns lookup by col.name). The planner emitted a column-accessor rename keyed by a stored column name that no longer exists in the new definition. The publish aborts.
Source
Thrown at crates/engine/src/update.rs:396
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 `{}`",
table_name,
col_name,
new_col_def.accessor_name,
);
stdb.alter_column_accessor_name(tx, table_id, col_schema.col_pos, new_col_def.accessor_name.clone())?;
}View on GitHub (pinned to 6dee26c6ef)
Solutions
- Clean-rebuild (cargo clean -p <crate> or delete target/), spacetime build, republish.
- Keep the stored column name pinned (#[spacetimedb::column(name = "hp")]) and rename only the Rust field; publish that alone.
- If the column itself must be renamed, do it in its own publish with nothing else changed.
- Align SDK/CLI/server versions with the live database's provenance.
- Dev only: spacetime publish --delete-data <db>.
- Persistent on clean builds: report as an auto_migrate planner bug with the module diff.
Example fix
// before: stored name AND accessor changed in one publish
pub struct Player {
#[spacetimedb::column(name = "hit_points")] // stored name was `hp`
pub hp: u32,
}
// after: keep stored name, change accessor only
pub struct Player {
#[spacetimedb::column(name = "hp")]
pub hit_points: u32,
} Defensive patterns
Strategy: validation
Validate before calling
use spacetimedb_schema::auto_migrate::AutoMigrateStep;
for step in &plan.steps {
if let AutoMigrateStep::ChangeColumnAccessorName(key, col_name) = step {
if let Some((_, tdef)) = plan.new.find_table(key) {
anyhow::ensure!(
tdef.columns.iter().any(|c| &c.name == col_name),
"column {} missing from new def of table {:?}", col_name, key
);
}
}
} Type guard
fn column_in_new_def(tdef: &TableDef, col_name: &str) -> bool {
tdef.columns.iter().any(|c| c.name == col_name)
} Try / catch
match update_database(&stdb, tx, &plan, ...).await {
Err(e) if e.to_string().contains("Column `")
&& e.to_string().contains("not found in table")
&& e.to_string().contains("ChangeColumnAccessorName") => {
// Column key drift: pin #[column(name)], republish the accessor change alone.
}
result => result?,
} Prevention
- Pin stored column names with #[column(name = "...")] before renaming fields.
- Never change a column's stored name and its accessor in the same publish.
- Review the generated schema (build artifacts) after renames to confirm keys are unchanged.
- Keep one schema change per publish.
When it happens
Trigger: Changing #[column(name = ...)] (or deleting the column) in the same publish where the column's accessor changed, so the planner's stored-name key misses in the new def; also column-name normalization/casing drift or submodule namespace differences between the def the planner saw and the def being applied.
Common situations: Renaming struct fields and their stored names in one commit; switching SDK versions that changed name normalization; copy-pasted column attributes after refactors.
Related errors
- ChangeColumnAccessorName: `{table_name}` not found in new mo
- ChangeTableAccessorName: `{table_name}` not found in new mod
- 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/da2b19f9386b1a95.
Report an issue: GitHub.