{"record":{"id":"37351f8b5e1e9c27","repo":"clockworklabs/SpacetimeDB","slug":"changetableaccessorname-table-name-not-found","errorCode":null,"errorMessage":"ChangeTableAccessorName: `{table_name}` not found in new module def","messagePattern":"ChangeTableAccessorName: `(.+?)` not found in new module def","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/engine/src/update.rs","lineNumber":373,"sourceCode":"                let stored_name = namespace.join_raw(&index_name.clone().into());\n                let table_id = stdb.table_id_from_name_mut(tx, &table_full_name)?.unwrap();\n                let table_schema = stdb.schema_for_table_mut(tx, table_id)?;\n\n                let index_schema = table_schema\n                    .indexes\n                    .iter()\n                    .find(|index| index.index_name == stored_name)\n                    .ok_or_else(|| anyhow::anyhow!(\"Index `{index_name}` not found in table `{table_full_name}`\"))?;\n\n                log!(logger, \"Dropping index `{index_name}` on table `{table_full_name}`\");\n                stdb.drop_index(tx, index_schema.index_id)?;\n            }\n            spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeTableAccessorName(table_name_key) => {\n                let (namespace, local) = table_name_key;\n                let table_name = joined(namespace, local);\n                let (_, new_table_def): (&ModuleDef, &spacetimedb_schema::def::TableDef) =\n                    plan.new.find_table(table_name_key).ok_or_else(|| {\n                        anyhow::anyhow!(\"ChangeTableAccessorName: `{table_name}` not found in new module def\")\n                    })?;\n\n                let table_id = stdb.table_id_from_name_mut(tx, &table_name)?.unwrap();\n                let new_alias = namespace.join(new_table_def.accessor_name.clone());\n\n                log!(\n                    logger,\n                    \"Changing table accessor name for `{table_name}` to `{new_alias}`\",\n                );\n                stdb.alter_table_accessor_name(tx, table_id, new_alias)?;\n            }\n            spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeColumnAccessorName(table_name_key, col_name) => {\n                let (namespace, local) = table_name_key;\n                let table_name = joined(namespace, local);\n                let (_, new_table_def): (&ModuleDef, &spacetimedb_schema::def::TableDef) =\n                    plan.new.find_table(table_name_key).ok_or_else(|| {\n                        anyhow::anyhow!(\"ChangeColumnAccessorName: `{table_name}` not found in new module def\")\n                    })?;","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/engine/src/update.rs#L355-L391","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: one publish combines accessor rename with rename + move to submodule\nmod guild {\n    #[spacetimedb::table(name = \"members\")] // was top-level `players`\n    pub struct Member {}                     // type was `Player`\n}\n\n// after: two publishes, stored name pinned\n// publish 1: accessor rename only, same stored name and location\n#[spacetimedb::table(name = \"players\")]\npub struct Member {}\n// publish 2 (separate): rename/move the table\nmod guild {\n    #[spacetimedb::table(name = \"members\")]\n    pub struct Member {}\n}","handlingStrategy":"validation","validationCode":"use spacetimedb_schema::auto_migrate::AutoMigrateStep;\n// Before applying an auto-migrate plan, verify every step resolves in the new def.\nfor step in &plan.steps {\n    if let AutoMigrateStep::ChangeTableAccessorName(key) = step {\n        if plan.new.find_table(key).is_none() {\n            anyhow::bail!(\"plan step references table {:?} missing from new module def\", key);\n        }\n    }\n}","typeGuard":"fn table_resolves_in_new_def(plan: &AutoMigratePlan, key: (&str, &str)) -> bool {\n    plan.new.find_table(key).is_some()\n}","tryCatchPattern":"match update_database(&stdb, tx, &plan, ...).await {\n    Err(e) if e.to_string().contains(\"ChangeTableAccessorName\")\n        && e.to_string().contains(\"not found in new module def\") => {\n        // Plan/def desync: fall back to split publishes or, on dev DBs, --delete-data.\n    }\n    result => result?,\n}","preventionTips":["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."],"tags":["spacetimedb","rust","schema-migration","publish","table-rename","accessor"],"backgroundTag":"schema-migration-plan-mismatch","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}