-
Notifications
You must be signed in to change notification settings - Fork 722
Description
Love SpaceTimeDB, congrats on your launch of 2.0, and that video was EPIC :D
Since I am a n00b coder, I ran into an issue and had an a.i. summarise;
Bug Summary
The TypeScript code generator (spacetime generate --lang typescript) produces PascalCase keys in the client tablesSchema object (e.g., Report, ReportCategory), but the SpacetimeDB wire protocol sends table names using the actual snake_case name field values (e.g., report, report_category). The SDK looks up tables by sourceName which is set to the PascalCase key, causing a crash when processing subscription messages.
Error
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'columns')
at DbConnection.parseRowList_fn (spacetimedb.js:6484:46)
at DbConnection.queryRowsToTableUpdates_fn (spacetimedb.js:6532:87)
at DbConnection.processMessage_fn (spacetimedb.js:6653:107)
Version
- SpacetimeDB CLI:
2.0.1(commita4d29daec8ed35ce4913a335b7210b9ae3933d00) spacetimedbnpm package:2.0.1- Module language: TypeScript
- Client framework: React (via
spacetimedb/react)
Root Cause
In the SDK source at src/lib/schema.ts:94, tableToSchema() sets sourceName: accName where accName is the object key from the generated tablesSchema:
// schema.ts line 93-95
return {
sourceName: accName, // ← set to the PascalCase key
accessorName: accName,
...
};In src/sdk/db_connection_impl.ts:207-216, the #sourceNameToTableDef map is keyed by table.sourceName:
this.#sourceNameToTableDef[table.sourceName] = table;When processing subscription messages at line 427, the SDK looks up the table using the wire table name (snake_case from the server):
const table = this.#sourceNameToTableDef[tableName]; // tableName = "report" from wire
const columnsArray = Object.entries(table.columns); // table is undefined → crashThe mismatch: the map has key "Report" (PascalCase from codegen) but the wire sends "report" (snake_case from DB).
Reproduction
- Create a TypeScript module with a table:
import { schema, table, t } from 'spacetimedb/server';
const User = table(
{ name: 'user', public: true },
{ identity: t.identity().primaryKey(), username: t.string().optional() }
);
const spacetimedb = schema({ User });
export default spacetimedb;- Publish and generate bindings:
spacetime publish mydb --no-config -s local
spacetime generate --lang typescript --out-dir ./src/module_bindings --module-path ./spacetimedb- The generated
src/module_bindings/index.tscontains:
const tablesSchema = __schema({
User: __table({ name: 'user', ... }, UserRow), // ← PascalCase key "User"
});- Connect from a client and subscribe:
conn.subscriptionBuilder().subscribe(['SELECT * FROM user']);- Crash — the server sends table name
"user"but the SDK only has"User"in its lookup map.
Workaround
Manually edit the generated index.ts to use snake_case keys matching the name field:
const tablesSchema = __schema({
user: __table({ name: 'user', ... }, UserRow), // was: User
report_category: __table({ name: 'report_category', ... }, ReportCategoryRow), // was: ReportCategory
});Then update all client references from tables.User to tables.user, etc.
Suggested Fix
The codegen should use the table's name field value as the key in tablesSchema, not the PascalCase-converted name. Alternatively, tableToSchema() could read the name from the table definition and use that as sourceName instead of accName.
Environment
- macOS 25.3.0 (Apple Silicon)
- Node.js v25.4.0
- Bun v1.3.8