{"record":{"id":"07c96eaed22aeb05","repo":"clockworklabs/SpacetimeDB","slug":"error-field-s-s-has-unique-constraint-cannot","errorCode":null,"errorMessage":"ERROR: Field %s.%s has unique constraint - cannot have default value","messagePattern":"ERROR: Field (.+?)\\.(.+?) has unique constraint - cannot have default value","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/include/spacetimedb/internal/v9_builder.h","lineNumber":657,"sourceCode":"    // Validate: default values cannot be used with primary_key, unique, or auto_inc\n    // Check if this column is in the primary key\n    for (uint16_t pk_col : table->primary_key) {\n        if (pk_col == field_idx) {\n            std::string error_msg = \"ERROR: Field \" + table_name + \".\" + field_name + \n                        \" has primary_key constraint - cannot have default value\";\n            fprintf(stderr, \"%s\", error_msg.c_str());\n            // fprintf(stderr, \"ERROR:  has primary_key constraint - cannot have default value\",\n            //          table_name.c_str(), field_name.c_str());\n            return;\n        }\n    }\n    \n    // Check if this column has a unique constraint\n    for (const auto& constraint : table->constraints) {\n        if (constraint.data.get_tag() == 0) {  // Unique constraint variant\n            const auto& unique_data = constraint.data.get<0>();\n            if (unique_data.columns.size() == 1 && unique_data.columns[0] == field_idx) {\n                fprintf(stderr, \"ERROR: Field %s.%s has unique constraint - cannot have default value\",\n                        table_name.c_str(), field_name.c_str());\n                return;\n            }\n        }\n    }\n    \n    // Check if this column has an auto_inc sequence\n    for (const auto& sequence : table->sequences) {\n        if (sequence.column == field_idx) {\n            fprintf(stderr, \"ERROR: Field %s.%s has auto_inc constraint - cannot have default value\",\n                    table_name.c_str(), field_name.c_str());\n            return;\n        }\n    }\n    \n    // Create the column default value structure\n    RawColumnDefaultValueV9 col_default;\n    col_default.table = table_name;","sourceCodeStart":639,"sourceCodeEnd":675,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-cpp/include/spacetimedb/internal/v9_builder.h#L639-L675","documentation":"AddColumnDefault rejects a default on a column that carries a single-column unique constraint: scanning table->constraints for the unique variant (tag 0) whose columns == {field_idx} finds a clash, prints this message (no trailing newline in this build) and returns, dropping the default. Unique columns derive their distinctness guarantee from enforcement at insert time, and a fixed default would either violate uniqueness on the second row or misrepresent it.","triggerScenarios":"A column annotated both unique (ST_UNIQUE) and with a column default; the unique constraint was registered first so table->constraints already contains it when AddColumnDefault runs for the same field index.","commonSituations":"Defaulting a username/email/token column that is also marked unique; adding unique to an existing defaulted column during a hardening pass; migrations that add defaults before checking existing constraints.","solutions":["Drop either the unique constraint or the default on that column — decide which behavior is intended","If unique values with a fallback are needed, compute them in the reducer (e.g. derive a unique suffix) instead of a static column default","Rebuild and verify the conflict message is gone and the schema matches intent"],"exampleFix":"// before\nST_UNIQUE(account, email);\nST_COLUMN_DEFAULT(account, email, \"unknown@invalid\");   // unique + default\n// after\nST_UNIQUE(account, email);\n// (default removed — reducer assigns email when not supplied)","handlingStrategy":"validation","validationCode":"// Policy check: refuse defaults on single-column unique constraints\nfor (const auto& c : table.constraints)\n    if (c.data.get_tag() == 0 && c.data.get<0>().columns.size() == 1\n        && c.data.get<0>().columns[0] == field_idx) /* forbid the default */;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When adding a unique constraint, audit the same column for an existing default (and vice versa)","Generate unique fallback values in reducers, not static defaults","Keep a lint/test that rejects unique+default pairs module-wide"],"tags":["spacetimedb","cpp","schema","constraint-conflict","unique-constraint","column-default"],"backgroundTag":"schema-constraint-conflict","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}