{"record":{"id":"ce40713f56ec8f1f","repo":"clockworklabs/SpacetimeDB","slug":"table-should-exist-in-the-database-for-addconstrai","errorCode":null,"errorMessage":"table should exist in the database for AddConstraint","messagePattern":"table should exist in the database for AddConstraint","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/engine/src/update.rs","lineNumber":486,"sourceCode":"                log!(\n                    logger,\n                    \"Dropping constraint `{constraint_name}` on table `{table_full_name}`\"\n                );\n                stdb.drop_constraint(tx, constraint_schema.constraint_id)?;\n            }\n            spacetimedb_schema::auto_migrate::AutoMigrateStep::AddConstraint(key) => {\n                let (namespace, constraint_name) = key;\n                let (owning_def, table_def) = plan\n                    .new\n                    .find_storing_table(namespace, constraint_name)\n                    .ok_or_else(|| anyhow::anyhow!(\"AddConstraint: `{constraint_name}` not found in new module def\"))?;\n                let table_full_name = joined(namespace, &table_def.name);\n                let constraint_def: &ConstraintDef = plan.new.lookup(key).ok_or_else(|| {\n                    anyhow::anyhow!(\"AddConstraint: constraint `{constraint_name}` not found in new module def\")\n                })?;\n                let table_id = stdb\n                    .table_id_from_name_mut(tx, &table_full_name)?\n                    .expect(\"table should exist in the database for AddConstraint\");\n                let mut constraint_schema =\n                    ConstraintSchema::from_module_def(owning_def, constraint_def, table_id, ConstraintId::SENTINEL);\n\n                // Apply namespace prefix for submodule constraints\n                constraint_schema.constraint_name = namespace.join_raw(&constraint_schema.constraint_name);\n                log!(\n                    logger,\n                    \"Adding constraint `{constraint_name}` on table `{table_full_name}`\"\n                );\n                stdb.create_constraint(tx, constraint_schema)?;\n            }\n            spacetimedb_schema::auto_migrate::AutoMigrateStep::AddSequence(key) => {\n                let (namespace, sequence_name) = key;\n                let (owning_def, table_def) = plan\n                    .new\n                    .find_storing_table(namespace, sequence_name)\n                    .ok_or_else(|| anyhow::anyhow!(\"AddSequence: `{sequence_name}` not found in new module def\"))?;\n                let table_full_name = joined(namespace, &table_def.name);","sourceCodeStart":468,"sourceCodeEnd":504,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/engine/src/update.rs#L468-L504","documentation":"Panic during SpacetimeDB automatic database migration. For an `AutoMigrateStep::AddConstraint` step, the migration plan says a constraint is being added to an existing table; the code looks the table up in the live database with `table_id_from_name_mut(tx, &table_full_name)` and `.expect(\"table should exist in the database for AddConstraint\")`. Panic means the plan referenced a table name that the database does not contain — an invariant break between the computed migration plan and actual DB state.","triggerScenarios":"Publishing an updated module whose auto-migration plan includes `AddConstraint` (e.g. adding a unique/index constraint) on a table whose fully-qualified name (namespace-qualified, submodules joined) is not present in the running database. This can happen when the table was created under a different name/path, the plan's namespace-joining logic produces a different string than what was stored, or the database state is stale/corrupted.","commonSituations":"Renaming tables or moving them between submodules while also adding constraints in the same publish; publishing against a database created by a much older SpacetimeDB version where table names were stored unprefixed; interrupted earlier migrations leaving partial state; mixing manual DDL with module-driven schema.","solutions":["Check whether the table was renamed or moved — if so, a rename/migration step must precede AddConstraint or you must publish as a breaking change (drop & recreate database).","Verify the constraint and table names printed in the error (`Adding constraint \\`X\\` on table \\`Y\\``) against the actual database schema (`spacetime sql <db> 'SELECT * FROM st_table'` style introspection).","If the database is disposable (dev), delete it and publish fresh instead of migrating.","If names match visually, suspect namespace-join differences (submodule prefixing) — report upstream with the module and its previous version, since this is an internal plan/DB mismatch."],"exampleFix":"# before: rename table AND add constraint in one publish -> plan adds constraint to a table name not in DB\nspacetime publish mydb --project mod2\n\n# after: publish the rename first (auto-migrate handles it), then add the constraint in a second publish\nspacetime publish mydb --project rename-only\nspacetime publish mydb --project with-constraint","handlingStrategy":"validation","validationCode":"// Before migrating, confirm every constrained table exists under its joined name\nfor (_, t) in plan.new.tables() {\n    if stdb.table_id_from_name_mut(tx, &joined(ns, &t.name))?.is_none() {\n        return Err(anyhow!(\"table `{}` missing; migration plan invalid\", t.name));\n    }\n}","typeGuard":null,"tryCatchPattern":"let r = std::panic::catch_unwind(AssertUnwindSafe(|| stdb.apply_auto_migrate(tx, plan)));\nmatch r { Ok(res) => res?, Err(_) => return Err(MigrationFailed::db_state_mismatch) }","preventionTips":["Don't rename/move tables and add constraints in the same publish; split into two publishes.","In dev, prefer `spacetime publish --delete-data` (fresh database) over risky auto-migrations.","Inspect the DB's table names before migrating when the module's history is unclear."],"tags":["rust","spacetimedb","migration","schema","constraints","database","panic"],"backgroundTag":"schema-migration-failed","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}