clockworklabs/SpacetimeDB · error

Precheck: sequence `{sequence_name}` not found in new module

Error message

Precheck: sequence `{sequence_name}` not found in new module def

What it means

Auto-migrate precheck CheckAddSequenceRangeValid: find_storing_table(namespace, sequence_name) failed, so no table in the new module def is responsible for storing the sequence named in the plan. The migration plan and the new def it was computed from are out of sync — an internal invariant break rather than user input error.

Source

Thrown at crates/engine/src/update.rs:220

/// Automatically migrate a database.
fn auto_migrate_database(
    stdb: &RelationalDB,
    tx: &mut MutTxId,
    auth_ctx: AuthCtx,
    plan: AutoMigratePlan,
    logger: &dyn UpdateLogger,
) -> anyhow::Result<UpdateResult> {
    log::info!("Running database update prechecks: {}", stdb.database_identity());
    // We used to memoize all table schemas upfront, which cause issue #3441.
    // Schema should be queries only when needed to ensure that any schema changes made during earlier migration steps are visible
    // to later steps.

    for precheck in plan.prechecks {
        match precheck {
            spacetimedb_schema::auto_migrate::AutoMigratePrecheck::CheckAddSequenceRangeValid(key) => {
                let (namespace, sequence_name) = key;
                let (_, table_def) = plan.new.find_storing_table(namespace, sequence_name).ok_or_else(|| {
                    anyhow::anyhow!("Precheck: sequence `{sequence_name}` not found in new module def")
                })?;
                let sequence_def: &SequenceDef = plan.new.lookup(key).ok_or_else(|| {
                    anyhow::anyhow!("Precheck: sequence `{sequence_name}` not found in new module def")
                })?;
                let table_full_name = joined(namespace, &table_def.name);
                let table_id = stdb.table_id_from_name_mut(tx, &table_full_name)?.unwrap();

                let ty = table_def
                    .get_column(sequence_def.column)
                    .ok_or_else(|| {
                        anyhow::anyhow!("Precheck failed: added sequence {sequence_name} refers to unknown column")
                    })?
                    .ty
                    .clone();

                // Convert `SequenceDef` min/max to `AlgebraicValue`s of the correct type.
                let min = ty
                    .saturating_value_from_i128(sequence_def.min_value.unwrap_or(1))

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Recompute the whole migration plan from the same ModuleDef you pass as plan.new
  2. If the plan came from spacetimedb_schema's differ, report upstream with both module defs and the key (namespace, sequence_name)
  3. Never hand-build AutoMigratePrecheck entries; derive them from the diff
Defensive patterns

Strategy: try-catch

Try / catch

match auto_migrate_database(&stdb, &mut tx, auth, &plan, &logger) {
    Err(e) if e.to_string().contains("Precheck: sequence") => {
        // plan/def desync: rebuild the plan from one consistent def, then retry once
        let plan2 = rebuild_plan_from(new_def)?;
        auto_migrate_database(&stdb, &mut tx, auth, &plan2, &logger)
    }
    r => r,
}

Prevention

When it happens

Trigger: A MigratePlan whose prechecks were computed from a different ModuleDef than plan.new; hand-constructed AutoMigratePrecheck entries; a bug in spacetimedb_schema's plan generation pairing a sequence with a table that no longer stores it.

Common situations: Custom tooling that assembles AutoMigratePlan pieces from multiple def versions; upstream diff bugs after schema-dsl changes; tests that build plans manually.

Related errors


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