{"record":{"id":"eec2222eb1257795","repo":"clockworklabs/SpacetimeDB","slug":"adding-non-unique-constraints-is-not-supported-co","errorCode":null,"errorMessage":"adding non-unique constraints is not supported (constraint on table {table_id})","messagePattern":"adding non-unique constraints is not supported \\(constraint on table (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/datastore/src/locking_tx_datastore/mut_tx.rs","lineNumber":2340,"sourceCode":"        Ok((table_id, schema))\n    }\n\n    /// Creates a constraint, making the corresponding indices unique.\n    ///\n    /// This inserts constraint metadata AND converts the in-memory indices\n    /// from non-unique to unique. If the existing data contains duplicate\n    /// values in the constrained columns, an error is returned.\n    ///\n    /// Pre-validation (before any system-table mutation):\n    /// - the constraint must be a unique one (the only kind supported today);\n    /// - the target table must already have at least one index on the constrained columns.\n    pub fn create_constraint(&mut self, constraint: ConstraintSchema) -> Result<ConstraintId> {\n        let table_id = constraint.table_id;\n\n        // (a) Only unique constraints are supported at the moment. Reject anything else\n        //     up front, before writing to `st_constraint`.\n        let Some(cols) = constraint.data.unique_columns().cloned() else {\n            return Err(anyhow::anyhow!(\n                \"adding non-unique constraints is not supported (constraint on table {table_id})\"\n            )\n            .into());\n        };\n        let col_list: ColList = cols.into();\n\n        // (b) A unique constraint must be backed by at least one index on the same columns.\n        //     Check on the committed table; the tx table's index set is kept in lockstep\n        //     with the committed one by the datastore, so agreement is an invariant.\n        {\n            let (_, (commit_table, _, _)) = self.get_or_create_insert_table_mut(table_id)?;\n            if commit_table.get_indexes_by_cols(&col_list).is_empty() {\n                return Err(anyhow::anyhow!(\n                    \"unique constraint on table {table_id} column(s) {col_list:?} \\\n                     requires at least one backing index on those columns\"\n                )\n                .into());\n            }","sourceCodeStart":2322,"sourceCodeEnd":2358,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/9e0d92412ff2248f401a8ad12d535f2b5ac30912/crates/datastore/src/locking_tx_datastore/mut_tx.rs#L2322-L2358","documentation":"Only unique constraints are supported by the datastore today. create_constraint extracts the constrained columns via constraint.data.unique_columns(); if the schema describes any other kind of constraint, it is rejected up front, before any system-table mutation, with the table id in the message.","triggerScenarios":"Calling MutTxId::create_constraint with a ConstraintData variant that carries no unique columns - e.g. a check-style or foreign-key-style constraint schema.","commonSituations":"Tooling or SQL layers that translate general SQL constraints; forward-ported schema dumps; tests exercising unsupported constraint kinds.","solutions":["Model only unique constraints; enforce other kinds (checks, FKs) in module reducers or application logic","Filter unsupported constraint kinds out of migration/DDL translation before they reach create_constraint","Track the SpacetimeDB roadmap for non-unique constraint support"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Filter to the supported constraint kind before calling the datastore\nfn is_supported_constraint(schema: &ConstraintSchema) -> bool {\n    schema.data.unique_columns().is_some()\n}\n\nif !is_supported_constraint(&schema) {\n    return Err(anyhow::anyhow!(\"only unique constraints are supported; enforce other rules in reducers\"));\n}","typeGuard":"fn is_unique_constraint(schema: &ConstraintSchema) -> bool {\n    schema.data.unique_columns().is_some()\n}","tryCatchPattern":"match tx.create_constraint(schema) {\n    Err(e) if e.to_string().contains(\"adding non-unique constraints is not supported\") => {\n        // Drop the unsupported constraint or reimplement it as reducer-level validation\n    }\n    other => other,\n}","preventionTips":["Map non-unique constraints to application/reducer logic during migration design","Keep a compatibility checklist when porting SQL schemas to SpacetimeDB"],"tags":["spacetimedb","datastore","constraint","unique","unsupported-feature"],"backgroundTag":"unsupported-constraint-type","analyzedSha":"9e0d92412ff2248f401a8ad12d535f2b5ac30912","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}