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
- 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()`.
- If you need a non-integer generated key, drop `.autoInc()` and generate the value in the reducer (e.g. a UUID).
- 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.
- 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
- Prefer the typed `t.u32()/t.u64()` builders so `.autoInc()` is only offered on integer columns.
- When rows are built from plain objects, validate autoInc columns before `table()` registration.
- Keep a unit test that constructs every table in the schema to catch this at test time, not publish time.
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
- schema entry ' ' looks like a default import; use `import *…
- schema entry ' ' must be a table or a submodule namespace…
- exporting something that is not a spacetime export
- HTTP handler ' ' was exported more than once
- multiple schemas are not supported
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)