{"record":{"id":"2d47e35678f82d9b","repo":"clockworklabs/SpacetimeDB","slug":"table-id-must-not-be-tableid-sentinel-in-se","errorCode":null,"errorMessage":"`table_id` must not be `TableId::SENTINEL` in `{seq:#?}`","messagePattern":"`table_id` must not be `TableId::SENTINEL` in `(.+?)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/datastore/src/locking_tx_datastore/mut_tx.rs","lineNumber":2147,"sourceCode":"\n    get_sequence_mut(seq_state, seq_id)?\n        .gen_next_value()\n        .ok_or_else(|| SequenceError::UnableToAllocate(seq_id).into())\n}\n\nimpl MutTxId {\n    /// Create a sequence.\n    /// Requires:\n    /// - `seq.sequence_id == SequenceId::SENTINEL`\n    /// - `seq.table_id != TableId::SENTINEL`\n    /// - `seq.sequence_name` must not be used for any other database entity.\n    ///\n    /// Ensures:\n    /// - The sequence metadata is inserted into the system tables (and other data structures reflecting them).\n    /// - The returned ID is unique and not `SequenceId::SENTINEL`.\n    pub fn create_sequence(&mut self, seq: SequenceSchema) -> Result<SequenceId> {\n        if seq.table_id == TableId::SENTINEL {\n            return Err(anyhow::anyhow!(\"`table_id` must not be `TableId::SENTINEL` in `{seq:#?}`\").into());\n        }\n\n        let table_id = seq.table_id;\n        let matching_system_table_schema = system_tables().iter().find(|s| s.table_id == table_id).cloned();\n\n        if seq.sequence_id != SequenceId::SENTINEL && matching_system_table_schema.is_none() {\n            return Err(anyhow::anyhow!(\"`sequence_id` must be `SequenceId::SENTINEL` in `{:#?}`\", seq).into());\n        }\n\n        let sequence_id = seq.sequence_id;\n\n        log::trace!(\n            \"SEQUENCE CREATING: {} for table: {} and col: {}\",\n            seq.sequence_name,\n            table_id,\n            seq.col_pos\n        );\n","sourceCodeStart":2129,"sourceCodeEnd":2165,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/9e0d92412ff2248f401a8ad12d535f2b5ac30912/crates/datastore/src/locking_tx_datastore/mut_tx.rs#L2129-L2165","documentation":"MutTxId::create_sequence rejects a SequenceSchema whose table_id equals TableId::SENTINEL. A sequence must be attached to a concrete existing table column; the sentinel indicates the field was never populated, so creation is refused before any st_sequences row is written.","triggerScenarios":"Calling create_sequence with a SequenceSchema built with the default/sentinel table_id - e.g. constructing the schema programmatically without resolving the owning table.","commonSituations":"Schema tooling and migrations that build SequenceSchema values from partial metadata; tests copying template schemas.","solutions":["Resolve the owning table's id (by name lookup in the transaction) and set seq.table_id before calling create_sequence","Assert at construction time that table_id differs from TableId::SENTINEL to fail closer to the bug"],"exampleFix":"// before\nlet seq = SequenceSchema { table_id: TableId::SENTINEL, .. };\nlet sequence_id = tx.create_sequence(seq)?;\n\n// after\nlet table_id = tx\n    .table_id_from_name(\"t\")\n    .ok_or_else(|| anyhow::anyhow!(\"table t does not exist\"))?\n    .into();\nlet seq = SequenceSchema { table_id, .. };\nlet sequence_id = tx.create_sequence(seq)?;","handlingStrategy":"type-guard","validationCode":"// Resolve the owning table before building the sequence schema\nlet table_id = tx\n    .table_id_from_name(\"t\")\n    .ok_or_else(|| anyhow::anyhow!(\"table t does not exist\"))?\n    .into();\nlet seq = SequenceSchema { table_id, .. };","typeGuard":"fn sequence_schema_has_table(seq: &SequenceSchema) -> bool {\n    seq.table_id != TableId::SENTINEL\n}","tryCatchPattern":"match tx.create_sequence(seq) {\n    Err(e) if e.to_string().contains(\"table_id` must not be `TableId::SENTINEL``\") => {\n        // Set the owning table id and retry\n    }\n    other => other,\n}","preventionTips":["Derive table ids from live lookups, never from templates or defaults","Validate schema structs before handing them to datastore APIs"],"tags":["spacetimedb","datastore","sequence","schema","sentinel"],"backgroundTag":"sentinel-id-misuse","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"}