{"record":{"id":"a4996298cacf658e","repo":"clockworklabs/SpacetimeDB","slug":"addconstraint-constraint-name-not-found-in-ne","errorCode":null,"errorMessage":"AddConstraint: `{constraint_name}` not found in new module def","messagePattern":"AddConstraint: `(.+?)` not found in new module def","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/engine/src/update.rs","lineNumber":479,"sourceCode":"\n                let constraint_schema = table_schema\n                    .constraints\n                    .iter()\n                    .find(|constraint| constraint.constraint_name == stored_name)\n                    .unwrap();\n\n                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            }","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/engine/src/update.rs#L461-L497","documentation":"Applying AddConstraint: the diff plans creating a constraint, but no table in the new module def reports storing it (plan.new.find_storing_table returns None). The constraint key in the step does not resolve in the new defs - the plan and the module definition set are inconsistent. The publish aborts before the constraint is created.","triggerScenarios":"Adding #[unique]/constraint attributes while also renaming or moving the table or the constrained columns in the same publish; constraint-name normalization or namespace-prefix differences between the def the planner diffed and the def being applied.","commonSituations":"Adding a unique constraint during a broader table refactor; submodule moves of newly-constrained tables; SDK version changes between build and publish.","solutions":["Clean-rebuild and republish.","Add the constraint in its own publish with no other schema edits.","Keep the owning table's name and location stable (pin with #[table(name = \"...\")]).","Align SDK/CLI/server versions across all machines and CI publishing the database.","Dev: spacetime publish --delete-data <db>.","File an issue with the plan if a clean single-change publish still fails."],"exampleFix":"// before: add #[unique] while moving the table to a submodule in one publish\nmod guild {\n    #[spacetimedb::table(name = \"members\")]\n    pub struct Member { #[unique] pub name: String }\n}\n\n// after: two publishes\n// 1) add the constraint on the unmoved table\n#[spacetimedb::table(name = \"players\")]\npub struct Player { #[unique] pub name: String }\n// 2) move the table separately","handlingStrategy":"validation","validationCode":"use spacetimedb_schema::auto_migrate::AutoMigrateStep;\nfor step in &plan.steps {\n    if let AutoMigrateStep::AddConstraint((namespace, cname)) = step {\n        if plan.new.find_storing_table(namespace, cname).is_none() {\n            anyhow::bail!(\"new def lacks storing table for constraint {}\", cname);\n        }\n    }\n}","typeGuard":"fn constraint_stores_in_new_def(plan: &AutoMigratePlan, ns: &str, cname: &str) -> bool {\n    plan.new.find_storing_table(ns, cname).is_some()\n}","tryCatchPattern":"match update_database(&stdb, tx, &plan, ...).await {\n    Err(e) if e.to_string().contains(\"AddConstraint\")\n        && e.to_string().contains(\"not found in new module def\") => {\n        // Split publishes: add the constraint with the table unchanged, refactor later.\n    }\n    result => result?,\n}","preventionTips":["Add constraints in a dedicated publish with the owning table otherwise unchanged.","Pin table names with #[table(name = \"...\")] before adding constraints.","Keep one schema change per publish.","Align SDK/CLI/server versions across build environments."],"tags":["spacetimedb","rust","schema-migration","constraint","unique","publish"],"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"}