clockworklabs/SpacetimeDB · error
ERROR: Field '%s' not found in table '%s'
Error message
ERROR: Field '%s' not found in table '%s'
What it means
AddFieldConstraint resolved the table and its field descriptors, but the requested field_name does not match any field_desc.name in the descriptor list, so it cannot compute the column index and drops the constraint. The comparison is exact and case-sensitive against the names produced by the row type's field registration.
Source
Thrown at crates/bindings-cpp/include/spacetimedb/internal/v9_builder.h:465
fprintf(stderr, "ERROR: No field descriptors found for table %s\n", table_name.c_str());
return;
}
const auto& field_descs = it->second.fields;
uint16_t field_idx = 0;
bool field_found = false;
// Find the field index
for (const auto& field_desc : field_descs) {
if (field_desc.name == field_name) {
field_found = true;
break;
}
field_idx++;
}
if (!field_found) {
fprintf(stderr, "ERROR: Field '%s' not found in table '%s'\n",
field_name.c_str(), table_name.c_str());
return;
}
// Add constraint based on type
int constraint_bits = static_cast<int>(constraint);
// Check for PrimaryKey (has specific bit 0b1000)
if (constraint_bits & 0b1000) { // PrimaryKey-specific bit
// Validate that there isn't already a primary key
if (!table->primary_key.empty()) {
// Set the error flag instead of crashing - this will be handled by preinit_99
SetMultiplePrimaryKeyError(table_name);
return; // Exit early to avoid adding the conflicting primary key
}
table->primary_key.push_back(field_idx);
// PrimaryKey implies Unique constraint and indexView on GitHub (pinned to 524b4487d9)
Solutions
- Verify the field string in the constraint macro exactly matches the C++ member name declared in the row struct (case-sensitive)
- If the member was renamed, update every constraint/index/default annotation that references it
- Confirm the field is declared in the same struct T that the macro uses, not in a base class or sibling type
- Republish and describe the table to confirm the constraint took effect
Example fix
// before
struct User { uint64_t user_id; std::string name; };
ST_UNIQUE(user, id); // 'id' not among descriptors ('user_id','name')
// after
struct User { uint64_t user_id; std::string name; };
ST_UNIQUE(user, user_id); Defensive patterns
Strategy: validation
Validate before calling
// Check the field name exists among registered descriptors before annotating: // after static init, for row type T: SpacetimeDB::field_registrar<T>::register_fields(); auto& descs = SpacetimeDB::get_table_descriptors(); // verify a field named 'id' exists for typeid(T) before adding ST_UNIQUE(T,"...","id")
Prevention
- Single-source field name strings: generate or share constants between struct and annotations where possible
- Rename fields and their annotations in the same commit
- Add a schema-diff test comparing published constraints against expectations
When it happens
Trigger: Renaming a struct member without updating the constraint macro's field string; passing the database column name when the descriptor uses the C++ member name (or vice versa); whitespace/typo differences in the quoted field name; constraining a field that exists only in a different type than T.
Common situations: Schema refactors where the member is renamed (e.g. userId -> user_id) but constraint annotations keep the old string; macro-generated field names that differ from expectations; copy-paste of constraint macros between similar tables.
Related errors
- ERROR: Field '%s' not found in table '%s' for multi-column i
- ERROR: Table '%s' not found when trying to add constraint to
- ERROR: No field descriptors found for table %s
- Unknown constraint type
- ERROR: Skipping multi-column index registration '%s.%s' beca
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/8211efdd860b3dd9.
Report an issue: GitHub.