clockworklabs/SpacetimeDB · error · Error
Cannot extract table name from query
Error message
Cannot extract table name from query
What it means
getQueryTableName(query) duck-types the three known builder shapes - FromBuilder (.table), TableRefImpl (.name), and SemijoinImpl (.sourceQuery) - and throws when the argument matches none. It is the exported helper that bridges arbitrary query-builder expressions to table names (sibling of getQueryAccessorName used by the framework hooks).
Source
Thrown at crates/bindings-typescript/src/lib/query.ts:1046
export function toComparableValue(value: any): any {
// Handle `ConnectionId` and `Identity`.
if (isHexSerializableLike(value)) {
return value.toHexString();
}
if (isTimestampLike(value)) {
return value.__timestamp_micros_since_unix_epoch__;
}
return value;
}
/**
* Extract the table name from a query builder expression.
*/
export function getQueryTableName(query: any): string {
if (query.table) return query.table.name; // FromBuilder
if (query.name) return query.name; // TableRefImpl
if (query.sourceQuery) return query.sourceQuery.table.name; // SemijoinImpl (source table)
throw new Error('Cannot extract table name from query');
}
/**
* Extract the accessor name from a query builder expression.
*/
export function getQueryAccessorName(query: any): string {
if (query.table) return query.table.accessorName; // FromBuilder
if (query.accessorName) return query.accessorName; // TableRefImpl
if (query.sourceQuery) return query.sourceQuery.table.accessorName; // SemijoinImpl
throw new Error('Cannot extract accessor name from query');
}
/**
* Extract the BooleanExpr from a query builder, if any.
*/
export function getQueryWhereClause(query: any): BooleanExpr<any> | undefined {
if (query.whereClause) return query.whereClause; // FromBuilder
return undefined; // TableRefImpl has no where clauseView on GitHub (pinned to 524b4487d9)
Solutions
- Pass the original builder expression (tables.user or tables.user.where(...)) instead of a built Query or plain object
- If you author a custom builder, expose one of the recognized shapes (.table, .name, or .sourceQuery)
- Extend getQueryTableName to recognize the new query kind
Example fix
// before const name = getQueryTableName(tables.user.build()); // built Query -> throws // after const name = getQueryTableName(tables.user);
Defensive patterns
Strategy: type-guard
Validate before calling
function isKnownQueryBuilder(q: unknown): boolean {
const c = q as Record<string, unknown> | null | undefined;
return Boolean(c && (c.table || c.name || c.sourceQuery));
} Type guard
type KnownQueryBuilder = { table: unknown } | { name: unknown } | { sourceQuery: unknown };
function isKnownQueryBuilder(q: unknown): q is KnownQueryBuilder {
const c = q as Record<string, unknown> | null | undefined;
return Boolean(c && (c.table || c.name || c.sourceQuery));
} Prevention
- Always pass builder expressions (table ref, .where chain, semijoin), never .build() results or literals
- Type hook wrappers to accept Query<TableDef> so plain objects are rejected at compile time
- When adding a new builder shape, update the extractors or expose a recognized field
When it happens
Trigger: Passing anything that is not a table ref, a .where(...) chain, or a semijoin result - e.g. the Query returned by .build(), a plain object literal, or a test mock - into getQueryTableName or into internal plumbing that calls it.
Common situations: New builder kinds (other joins, aggregations) the extractor has not learned; tests mocking builders as plain objects; re-feeding a built Query back into an API that expects the builder.
Related errors
- cannot serialize refs without a typespace
- cannot deserialize refs without a typespace
- could not serialize result: object had neither a `ok` nor an
- Could not serialize sum type; unknown tag ${value.tag}
- Cannot extract accessor name from query
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/26384cc1c255c710.
Report an issue: GitHub.