clockworklabs/SpacetimeDB · critical

missing system table sequence id for sequence {} of table {}

Error message

missing system table sequence id for sequence {} of table {}

What it means

SpacetimeDB constructs its system-table schemas at startup and, in the normalizer, assigns every sequence attached to a system table a reserved id from the static SEQUENCE_IDS registry (mirroring the constraint-id lookup just above it). If a system table's sequence name is missing from that map, the code panics; the normalizer also forces sequence.start into the ST_RESERVED_SEQUENCE_RANGE. This is an internal registration invariant reachable only by code that defines system tables (spacetimedb core or a fork), not by user DDL.

Source

Thrown at crates/datastore/src/system_tables.rs:846

        });
    }
    for constraint in &mut result.constraints {
        constraint.constraint_id = CONSTRAINT_IDS
            .get(&constraint.constraint_name[..])
            .copied()
            .unwrap_or_else(|| {
                panic!(
                    "missing system table constraint id for constraint {} of table {}",
                    constraint.constraint_name, result.table_name
                )
            });
    }
    for sequence in &mut result.sequences {
        sequence.sequence_id = SEQUENCE_IDS
            .get(&sequence.sequence_name[..])
            .copied()
            .unwrap_or_else(|| {
                panic!(
                    "missing system table sequence id for sequence {} of table {}",
                    sequence.sequence_name, result.table_name
                )
            });
        sequence.start = ST_RESERVED_SEQUENCE_RANGE as i128 + 1;
        // sequence.allocated = ST_RESERVED_SEQUENCE_RANGE as i128;
    }
    if let Some(sch) = result.schedule {
        panic!(
            "system tables cannot have schedules, but table {}: {sch:?}",
            result.table_name
        );
    }
    result.normalize();
    // Note, if we ever added system tables with schedules, we would need to set their IDs here too.
    result
}

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Add the sequence name and a unique reserved id to SEQUENCE_IDS alongside the other system sequence registrations.
  2. Or remove the sequence from that system table's schema.
  3. Run the datastore/system-table tests, which construct every system table and will catch the miss.
Defensive patterns

Strategy: try-catch

Validate before calling

// core devs: registry-completeness test next to SEQUENCE_IDS
#[test]
fn all_system_table_sequences_registered() {
    for st in system_tables() {
        for seq in &st.sequences {
            assert!(
                SEQUENCE_IDS.contains_key(&seq.sequence_name[..]),
                "unregistered system sequence {}",
                seq.sequence_name
            );
        }
    }
}

Try / catch

// keep boot-time panics from failing silently in CI
let r = std::panic::catch_unwind(build_system_tables);
if r.is_err() {
    // a system table sequence lacks a reserved id: fix SEQUENCE_IDS before merging
}

Prevention

When it happens

Trigger: A developer adds a system table with a sequence but does not register its name in the SEQUENCE_IDS map in system_tables.rs; panics during system schema construction at boot or in datastore tests.

Common situations: Contributing new system tables to spacetimedb core; custom forks adding system tables; rebasing across refactors that renamed sequences without updating the registry.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/760b65d22544af17. Report an issue: GitHub.