clockworklabs/SpacetimeDB · error · TypeError

invalid sequence type

Error message

invalid sequence type

What it means

When the runtime builds a table view (`makeTableView` in runtime.ts), it inspects every auto-increment sequence on the table and picks the 'sentinel' value a caller passes to trigger sequence generation: `0` for integer types that fit a JS number (U8..I32) and `0n` for wide integers (U64..I256). If the sequence column's algebraic type is anything else, the switch falls through to `invalid sequence type`. This is a schema-definition error surfaced at module build/first table access, not a data error.

Solutions

  1. Find the auto-increment column in the failing table and change its builder to an integer type, e.g. `t.u32()` or `t.u64()`, before `.autoInc()`.
  2. If you need a non-integer generated key, drop `.autoInc()` and generate the value in the reducer (e.g. a UUID).
  3. If the table is built dynamically, validate each column before publishing: only U8/I8/U16/I16/U32/I32/U64/I64/U128/I128/U256/I256 may carry autoInc.
  4. Re-run `spacetime build`/`publish` after fixing; the error names the table via the build log context.

Example fix

// before
const users = table({}, {
  id: t.string().primaryKey().autoInc(), // string cannot be a sequence
});

// after
const users = table({}, {
  id: t.u64().primaryKey().autoInc(),
});
Defensive patterns

Strategy: type-guard

Validate before calling

// For dynamically built tables: only integer columns may carry autoInc.
const INTEGER_TAGS = new Set(['U8','I8','U16','I16','U32','I32','U64','I64','U128','I128','U256','I256']);
function assertAutoIncColumns(row: Record<string, any>) {
  for (const [name, col] of Object.entries(row)) {
    if (col?.builderMeta?.autoInc && !INTEGER_TAGS.has(col?.algebraicType?.tag)) {
      throw new Error(`column ${name}: autoInc requires an integer type`);
    }
  }
}

Type guard

type IsIntegerColumn<C> = C extends { algebraicType: { tag: ('U8'|'I8'|'U16'|'I16'|'U32'|'I32'|'U64'|'I64'|'U128'|'I128'|'U256'|'I256') } } ? true : false;

Prevention

When it happens

Trigger: Applying `.autoInc()` to a column whose type is not an integer SATS primitive (string, bool, float, identity, timestamp...); building a table dynamically (plain objects instead of `t.*` builders) so the type-level protections are bypassed; hand-constructing table/sequence metadata where `seq.column` points at a non-integer column.

Common situations: Trying to auto-increment a `t.string()` primary key; migrating a schema where an autoInc flag ends up on a changed column type; using dynamic/`any`-typed row builders that defeat the compile-time `autoInc()` restrictions.

Related errors


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

Appendix: source

Thrown at crates/bindings-typescript/src/server/runtime.ts:1119

    switch (colType.tag) {
      case 'U8':
      case 'I8':
      case 'U16':
      case 'I16':
      case 'U32':
      case 'I32':
        sequenceTrigger = 0;
        break;
      case 'U64':
      case 'I64':
      case 'U128':
      case 'I128':
      case 'U256':
      case 'I256':
        sequenceTrigger = 0n;
        break;
      default:
        throw new TypeError('invalid sequence type');
    }
    return {
      colName: col.name!,
      sequenceTrigger,
      deserialize: AlgebraicType.makeDeserializer(colType, typespace),
    };
  });
  const hasAutoIncrement = sequences.length > 0;

  const iter = () =>
    tableIterator(sys.datastore_table_scan_bsatn(table_id), deserializeRow);

  const integrateGeneratedColumns = hasAutoIncrement
    ? (row: RowType<any>, ret_buf: DataView) => {
        BINARY_READER.reset(ret_buf);
        for (const { colName, deserialize, sequenceTrigger } of sequences) {
          if (row[colName] === sequenceTrigger) {
            row[colName] = deserialize(BINARY_READER);

View on GitHub (pinned to eddf9f5014)