clockworklabs/SpacetimeDB · error
ERROR: Field %s.%s has auto_inc constraint - cannot have def
Error message
ERROR: Field %s.%s has auto_inc constraint - cannot have default value
What it means
AddColumnDefault refuses defaults on auto-incremented columns: it scans table->sequences and finds a sequence whose column == field_idx (registered earlier by the auto_inc/ST_AUTO_INC path), prints this message and returns, dropping the default. Auto-inc columns are populated by their sequence, so a serialized default would race the sequence generator.
Source
Thrown at crates/bindings-cpp/include/spacetimedb/internal/v9_builder.h:667
}
}
// Check if this column has a unique constraint
for (const auto& constraint : table->constraints) {
if (constraint.data.get_tag() == 0) { // Unique constraint variant
const auto& unique_data = constraint.data.get<0>();
if (unique_data.columns.size() == 1 && unique_data.columns[0] == field_idx) {
fprintf(stderr, "ERROR: Field %s.%s has unique constraint - cannot have default value",
table_name.c_str(), field_name.c_str());
return;
}
}
}
// Check if this column has an auto_inc sequence
for (const auto& sequence : table->sequences) {
if (sequence.column == field_idx) {
fprintf(stderr, "ERROR: Field %s.%s has auto_inc constraint - cannot have default value",
table_name.c_str(), field_name.c_str());
return;
}
}
// Create the column default value structure
RawColumnDefaultValueV9 col_default;
col_default.table = table_name;
col_default.col_id = field_idx;
col_default.value = serialized_value;
// Create the misc export entry with ColumnDefaultValue variant (variant 0)
RawMiscModuleExportV9 export_entry;
export_entry.set<0>(col_default);
// Add to the module's misc_exports
GetV9Module().misc_exports.push_back(export_entry);
}View on GitHub (pinned to 524b4487d9)
Solutions
- Remove the column default from the auto-inc column — the sequence supplies values
- If a starting value is needed, set the sequence's min/start (as done in the sequence registration path) instead of a column default
- Rebuild and confirm the conflict message is gone
Example fix
// before ST_AUTO_INC(order, id); ST_COLUMN_DEFAULT(order, id, 1000); // auto_inc + default // after ST_AUTO_INC(order, id); // (default removed; configure the sequence start instead)
Defensive patterns
Strategy: validation
Validate before calling
// Policy check: refuse defaults on sequenced (auto_inc) columns
for (const auto& seq : table.sequences)
if (seq.column == field_idx) /* forbid the ST_COLUMN_DEFAULT annotation */; Prevention
- Configure sequence start/min instead of defaults on auto-inc columns
- Never combine ST_AUTO_INC and ST_COLUMN_DEFAULT on one column
- Add a schema lint rule for auto_inc + default pairs
When it happens
Trigger: A column annotated with both ST_AUTO_INC/auto_inc and ST_COLUMN_DEFAULT on the same table; the sequence registration ran first, so table->sequences contains the column when the default registration is validated.
Common situations: Adding a default to an id column that was already auto_inc; schema refactors merging annotations; porting from a SQL schema where DEFAULT nextval-style habits carried over.
Related errors
- ERROR: Field %s.%s has primary_key constraint - cannot have
- ERROR: Field %s.%s has unique constraint - cannot have defau
- ERROR: Skipping default-value registration '%s.%s' because c
- ERROR: Table '%s' not found for default value on field '%s'
- ERROR: Skipping multi-column index registration '%s.%s' beca
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/936f30692989abd1.
Report an issue: GitHub.