clockworklabs/SpacetimeDB · error
`sequence_id` must be `SequenceId::SENTINEL` in `{:#?}`
Error message
`sequence_id` must be `SequenceId::SENTINEL` in `{:#?}` What it means
MutTxId::create_sequence requires sequence_id to be SequenceId::SENTINEL for user tables so the datastore can allocate a fresh unique id. Pre-assigned ids are only tolerated when the sequence targets a system table (matched against system_tables()). Passing a concrete sequence_id for a user sequence violates the API contract and is rejected.
Source
Thrown at crates/datastore/src/locking_tx_datastore/mut_tx.rs:2154
/// Create a sequence.
/// Requires:
/// - `seq.sequence_id == SequenceId::SENTINEL`
/// - `seq.table_id != TableId::SENTINEL`
/// - `seq.sequence_name` must not be used for any other database entity.
///
/// Ensures:
/// - The sequence metadata is inserted into the system tables (and other data structures reflecting them).
/// - The returned ID is unique and not `SequenceId::SENTINEL`.
pub fn create_sequence(&mut self, seq: SequenceSchema) -> Result<SequenceId> {
if seq.table_id == TableId::SENTINEL {
return Err(anyhow::anyhow!("`table_id` must not be `TableId::SENTINEL` in `{seq:#?}`").into());
}
let table_id = seq.table_id;
let matching_system_table_schema = system_tables().iter().find(|s| s.table_id == table_id).cloned();
if seq.sequence_id != SequenceId::SENTINEL && matching_system_table_schema.is_none() {
return Err(anyhow::anyhow!("`sequence_id` must be `SequenceId::SENTINEL` in `{:#?}`", seq).into());
}
let sequence_id = seq.sequence_id;
log::trace!(
"SEQUENCE CREATING: {} for table: {} and col: {}",
seq.sequence_name,
table_id,
seq.col_pos
);
// Insert the sequence row into st_sequences
// NOTE: Because st_sequences has a unique index on sequence_name, this will
// fail if the table already exists.
let mut sequence_row = StSequenceRow {
sequence_id,
sequence_name: seq.sequence_name,
table_id,View on GitHub (pinned to 9e0d92412f)
Solutions
- Reset seq.sequence_id to SequenceId::SENTINEL and let create_sequence allocate a new id
- When replaying/restoring schema, drop the old ids for user objects and remap references after creation
Example fix
// before: replaying a captured schema with its old id
let seq = SequenceSchema { sequence_id: old_sequence_id, .. };
let new_id = tx.create_sequence(seq)?; // -> sequence_id must be SENTINEL
// after: let the datastore assign the id
let seq = SequenceSchema { sequence_id: SequenceId::SENTINEL, .. };
let new_id = tx.create_sequence(seq)?; Defensive patterns
Strategy: type-guard
Validate before calling
// When creating user sequences, always let the datastore assign the id
let seq = SequenceSchema { sequence_id: SequenceId::SENTINEL, .. }; Type guard
fn sequence_id_is_unset(seq: &SequenceSchema) -> bool {
seq.sequence_id == SequenceId::SENTINEL || targets_system_table(seq.table_id)
} Try / catch
match tx.create_sequence(seq) {
Err(e) if e.to_string().contains("sequence_id` must be `SequenceId::SENTINEL``") => {
// Reset sequence_id to the sentinel and retry; remap the returned id afterwards
}
other => other,
} Prevention
- Never copy sequence ids across databases or replays
- In restore tooling, strip ids from user schema objects and remap after creation
When it happens
Trigger: Re-inserting a sequence with a previously allocated sequence_id on a user table; restoring schema objects by replaying old schema dumps; building SequenceSchema with a hardcoded id.
Common situations: Backup/restore tooling that replays captured schema rows; migrations that copy ids from another database; tests reusing fixture schemas.
Related errors
- `table_id` must not be `TableId::SENTINEL` in `{seq:#?}`
- `table_id` must not be `TableId::SENTINEL` in `{index_schema
- `table_id` must not be `TableId::SENTINEL` in `{constraint:#
- unique constraint on table {table_id} column(s) {col_list:?}
- Index '${indexLabel}' on table '${tableLabel}' must define a
AI-assisted analysis of clockworklabs/SpacetimeDB@9e0d92412f (2026-08-20).
Data as JSON: /api/errors/bd8692b2449d430f.
Report an issue: GitHub.