clockworklabs/SpacetimeDB · error
ERROR: Skipping default-value registration '%s.%s' because c
Error message
ERROR: Skipping default-value registration '%s.%s' because circular reference error is set
What it means
The V10 builder refuses to register a column default value (AddColumnDefault) because g_circular_ref_error is already set from an earlier type-registration cycle. The skip protects the builder from stacking registrations onto a module whose type graph is known-broken; the underlying circular-reference error is reported separately and preinit_99 will fail the module. Treat this line as a symptom, not the root cause.
Source
Thrown at crates/bindings-cpp/include/spacetimedb/internal/v10_builder.h:260
"table='" + table_name + "' index='" + index_name + "' field='" + field_name + "' was not found");
return;
}
}
std::string generated_name = table_name + "_" + field_names[0];
for (size_t i = 1; i < field_names.size(); ++i) {
generated_name += "_" + field_names[i];
}
generated_name += "_idx_btree";
table_it->indexes.push_back(CreateBTreeIndex(table_name, generated_name, field_indexes, index_name));
}
template<typename T>
void AddColumnDefault(const std::string& table_name,
const std::string& field_name,
const std::vector<uint8_t>& serialized_value) {
if (g_circular_ref_error) {
std::fprintf(stderr, "ERROR: Skipping default-value registration '%s.%s' because circular reference error is set\n",
table_name.c_str(), field_name.c_str());
return;
}
auto table_it = FindTable(table_name);
if (table_it == tables_.end()) {
SetConstraintRegistrationError(
"TABLE_NOT_FOUND",
"table='" + table_name + "' default field='" + field_name + "' references an unknown table");
return;
}
SpacetimeDB::field_registrar<T>::register_fields();
auto& descriptor_map = SpacetimeDB::get_table_descriptors();
auto it = descriptor_map.find(&typeid(T));
if (it == descriptor_map.end()) {
SetConstraintRegistrationError(
"NO_FIELD_DESCRIPTORS",
"table='" + table_name + "' default field='" + field_name + "' has no registered field descriptors");View on GitHub (pinned to 524b4487d9)
Solutions
- Find the '[CIRCULAR REFERENCE DETECTED]' block earlier in stderr; it names the type and shows the chain (e.g. A -> B -> A)
- Remove the cycle by storing IDs/indices instead of embedded values in the offending type
- Rebuild — once g_circular_ref_error is never set, this message goes away and the default registers normally
- Verify the rebuilt module publishes and the column default appears in the schema (describe the table after publish)
Example fix
// before — cycle + default: default registration skipped
struct Config {
uint64_t id;
std::optional<Config> parent; // cycle: Config -> Config
};
// after
struct Config {
uint64_t id;
std::optional<uint64_t> parent_id; // acyclic; default value now registers
}; Defensive patterns
Strategy: validation
Validate before calling
// After module static init (e.g. in a test binary): #include <spacetimedb/internal/module_type_registration.h> ASSERT_FALSE(SpacetimeDB::Internal::g_circular_ref_error) << "fix the type cycle before trusting column defaults";
Prevention
- Model relationships with ID references, not embedded values
- Run a schema smoke test after adding any column default so silent skips fail CI
- Verify published schema (describe the table) rather than assuming the default was applied
When it happens
Trigger: A row type in a cycle (directly or transitively) is used on a table whose macro also declares a column default (ST_COLUMN_DEFAULT / AddColumnDefault with a serialized BSATN value). Type registration runs first during static init, sets the flag, and this default-value registration for '<table>.<field>' is then dropped.
Common situations: Adding a default clause to a table whose row type embeds itself (linked-list node, hierarchy node); introducing a new cross-referencing type pair while defaults already existed; version upgrades that change when/where type registration happens so a previously latent cycle gets detected.
Related errors
- ERROR: Skipping multi-column index registration '%s.%s' beca
- ERROR: Skipping reducer registration '%s' because circular r
- ERROR: Skipping lifecycle reducer registration '%s' because
- ERROR: Skipping view registration '%s' because circular refe
- ERROR: Skipping procedure registration '%s' because circular
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/74e183a404cc909b.
Report an issue: GitHub.