{"record":{"id":"7b1d39af5168e78d","repo":"clockworklabs/SpacetimeDB","slug":"error-constraint-registration-failed-s-s","errorCode":null,"errorMessage":"ERROR: Constraint registration failed [%s] %s\n","messagePattern":"ERROR: Constraint registration failed \\[(.+?)\\] (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/src/internal/Module.cpp","lineNumber":93,"sourceCode":"    static std::string g_constraint_registration_error_code = \"\";\n    static std::string g_constraint_registration_error_details = \"\";\n    \n    // External global flags for circular reference detection (defined in module_type_registration.cpp)\n    extern bool g_circular_ref_error;\n    extern std::string g_circular_ref_type_name;\n    \n    // Function to set the multiple primary key error flag\n    void SetMultiplePrimaryKeyError(const std::string& table_name) {\n        g_multiple_primary_key_error = true;\n        g_multiple_primary_key_table_name = table_name;\n        fprintf(stderr, \"ERROR: Multiple primary keys detected in table '%s'\\n\", table_name.c_str());\n    }\n\n    void SetConstraintRegistrationError(const std::string& code, const std::string& details) {\n        g_constraint_registration_error = true;\n        g_constraint_registration_error_code = code;\n        g_constraint_registration_error_details = details;\n        fprintf(stderr, \"ERROR: Constraint registration failed [%s] %s\\n\", code.c_str(), details.c_str());\n    }\n    \n    // Register a reducer handler (called by V9Builder during registration)\n    void RegisterReducerHandler(const std::string& name, \n                                std::function<void(ReducerContext&, BytesSource)> handler,\n                                std::optional<Lifecycle> lifecycle) {\n        g_reducer_handlers.push_back({name, handler, lifecycle});\n    }\n    \n    // Register a view handler (called by V9Builder during registration)\n    void RegisterViewHandler(const std::string& name,\n                            std::function<std::vector<uint8_t>(ViewContext&, BytesSource)> handler) {\n        g_view_handlers.push_back({name, handler});\n    }\n    \n    // Register an anonymous view handler (called by V9Builder during registration)\n    void RegisterAnonymousViewHandler(const std::string& name,\n                                     std::function<std::vector<uint8_t>(AnonymousViewContext&, BytesSource)> handler) {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-cpp/src/internal/Module.cpp#L75-L111","documentation":"Generic constraint-registration failure reported by SetConstraintRegistrationError(code, details). V10Builder calls it with a machine-readable code for many schema mistakes: TABLE_NO_FIELD_DESCRIPTORS, NO_FIELD_DESCRIPTORS, FIELD_NOT_FOUND, TABLE_NOT_FOUND, MULTI_INDEX_EMPTY, DEFAULT_ON_PRIMARY_KEY and others (see include/spacetimedb/internal/v10_builder.h). The flag makes __preinit__99_validate_types replace the module with error type ERROR_CONSTRAINT_REGISTRATION_<code>, so the publish fails with that name on the server.","triggerScenarios":"A FIELD_Unique/FIELD_Index macro naming a field that is not in the table's registered field descriptors (FIELD_NOT_FOUND); a multi-column index registered with an empty field list (MULTI_INDEX_EMPTY); a constraint applied before the table itself is registered (TABLE_NOT_FOUND); a table type whose field_registrar<T> produced no descriptors; a column default applied to the primary-key column (DEFAULT_ON_PRIMARY_KEY).","commonSituations":"Renaming a struct member without updating the adjacent FIELD_* macro; splitting table and constraint macros across translation units so preinit ordering registers constraints first; adding defaults to key columns when copying an ORM schema.","solutions":["Read the bracketed code and details string: FIELD_NOT_FOUND -> correct the field name in the constraint/index macro to match the struct member","TABLE_NOT_FOUND -> ensure the table registration macro for that table is compiled before/with the constraint macros (same header or TU)","MULTI_INDEX_EMPTY -> give the multi-column index at least one column name","NO_FIELD_DESCRIPTORS / TABLE_NO_FIELD_DESCRIPTORS -> make sure the table struct uses the SpacetimeDB table registration so field_registrar<T>::register_fields() populates descriptors","DEFAULT_ON_PRIMARY_KEY -> remove the column default from the primary-key column"],"exampleFix":"// before\nstruct User { uint64_t user_id; std::string name; };\nFIELD_Unique(User, usr_id); // typo -> FIELD_NOT_FOUND\n\n// after\nFIELD_Unique(User, user_id);","handlingStrategy":"validation","validationCode":"// compile-time existence check next to each constraint macro: a typo'd\n// member pointer fails to build before publish\nstatic_assert(&User::user_id != nullptr,\n              \"User.user_id must exist for FIELD_Unique(User, user_id)\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Put FIELD_* and index macros directly under the struct they constrain, in the same translation unit","Rename fields and macros together in one change; let the compiler's member-pointer checks catch typos","Publish to a dev database in CI so constraint codes surface before production"],"tags":["spacetimedb","cpp","schema","constraints","registration"],"backgroundTag":"schema-constraint-validation-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"}