{"record":{"id":"dc2bb0c8d957c403","repo":"clockworklabs/SpacetimeDB","slug":"error-no-field-descriptors-found-for-table-s","errorCode":null,"errorMessage":"ERROR: No field descriptors found for table %s\n","messagePattern":"ERROR: No field descriptors found for table (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/include/spacetimedb/internal/v9_builder.h","lineNumber":447,"sourceCode":"void V9Builder::AddFieldConstraint(const std::string& table_name,\n                                   const std::string& field_name,\n                                   FieldConstraint constraint) {\n    // AddFieldConstraint implementation\n    \n    // Find the existing table by name\n    RawTableDefV9* table = findTableByName(table_name);\n    if (!table) {\n        fprintf(stderr, \"ERROR: Table '%s' not found when trying to add constraint to field '%s'\\n\",\n                table_name.c_str(), field_name.c_str());\n        return;\n    }\n    \n    // Get field descriptors to find the field index\n    SpacetimeDB::field_registrar<T>::register_fields();\n    auto& descriptor_map = SpacetimeDB::get_table_descriptors();\n    auto it = descriptor_map.find(&typeid(T));\n    if (it == descriptor_map.end()) {\n        fprintf(stderr, \"ERROR: No field descriptors found for table %s\\n\", table_name.c_str());\n        return;\n    }\n    \n    const auto& field_descs = it->second.fields;\n    uint16_t field_idx = 0;\n    bool field_found = false;\n    \n    // Find the field index\n    for (const auto& field_desc : field_descs) {\n        if (field_desc.name == field_name) {\n            field_found = true;\n            break;\n        }\n        field_idx++;\n    }\n    \n    if (!field_found) {\n        fprintf(stderr, \"ERROR: Field '%s' not found in table '%s'\\n\", ","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-cpp/include/spacetimedb/internal/v9_builder.h#L429-L465","documentation":"After AddFieldConstraint calls SpacetimeDB::field_registrar<T>::register_fields(), it looks up the field descriptor map by &typeid(T). If T never produced descriptors, the lookup fails and the constraint is dropped with this message. In practice it means the template type T used by the constraint macro is not (the same type identity as) the row type whose fields were registered for the table.","triggerScenarios":"Passing a wrapper/alias/base type instead of the actual row struct to the constraint macro; register_fields registering descriptors under a different type identity than typeid(T> (cv-qualified or typedef-diverged instantiations); the row type's field_registrar specialization missing because the type lacks the required field registration macro.","commonSituations":"Using a typedef or using-alias for the row type in one file so typeid differs; templated table helpers where T is deduced as a reference/const-qualified variant; splitting table definition and constraint macros across headers compiled with different type spellings; forgetting the field-registration macro inside the struct.","solutions":["Ensure the constraint macro receives the exact row struct type that the table macro used, spelled identically in both places","Confirm the row struct contains its field registration macro (field_registrar specialization) so register_fields populates descriptors","Avoid typedef/alias indirection for row types in constraint registrations","If the table is templated, check that no cv/reference qualifications leak into T before the typeid lookup"],"exampleFix":"// before — constraint registered for a different type identity\nusing UserRow = User;\nST_UNIQUE_ON_TYPE(UserRow, \"users\", id);   // typeid(UserRow) may not match\n// after\nST_UNIQUE_ON_TYPE(User, \"users\", id);       // same type as the table registration","handlingStrategy":"validation","validationCode":"// Assert descriptors exist for the exact row type before/after registration:\n#include <spacetimedb/spacetimedb.h> // provides get_table_descriptors\nbool HasDescriptorsFor(const std::type_index& ti) {\n    return SpacetimeDB::get_table_descriptors().count(ti.operator()) != 0; // adapt to API shape\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Spell the row type identically at the table and constraint sites — no typedefs or aliases","Include the field registration macro in every row struct","Beware cv/reference-qualified template instantiations changing typeid"],"tags":["spacetimedb","cpp","schema","field-descriptors","typeid-mismatch","constraint"],"backgroundTag":"schema-field-descriptor-missing","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}