clockworklabs/SpacetimeDB · error · Error

Could not find SpacetimeDB client! Did you forget to call…

Error message

Could not find SpacetimeDB client! Did you forget to call `createSpacetimeDBProvider`? `useTable` must be used in a Svelte component tree under a component that called `createSpacetimeDBProvider`.

What it means

useTable in the Svelte bindings wraps useSpacetimeDB() in a try/catch and rethrows this message when the context store is missing. It fires under exactly the same conditions as the base hook: no ancestor called createSpacetimeDBProvider during component initialization, so there is no connection store to subscribe with.

Solutions

  1. Create the provider once in the root layout component: `const db = createSpacetimeDBProvider(builder)`
  2. Move any component calling useTable under that layout/component in the tree
  3. Ensure no `await` separates component init from the createSpacetimeDBProvider call
  4. For isolated tests, create the provider in the test harness component that wraps the component under test

Example fix

<!-- before -->
<script lang="ts">
  const [rows, isReady] = useTable(tables.player); // throws
</script>

<!-- after: root +layout.svelte -->
<script lang="ts">
  import { createSpacetimeDBProvider } from '@clockworklabs/spacetime-db-svelte';
  const db = createSpacetimeDBProvider(builder);
</script>
<slot />

<!-- any descendant may now call useTable safely -->
Defensive patterns

Strategy: validation

Validate before calling

import { hasContext } from 'svelte';
import { SPACETIMEDB_CONTEXT_KEY } from './connection_state';

export const canUseTable = () => hasContext(SPACETIMEDB_CONTEXT_KEY);

Try / catch

// In Svelte 5, wrap risky children in an error boundary snippet; otherwise guard with canUseTable() before calling useTable

Prevention

When it happens

Trigger: Calling useTable(tables.x) or useTable(tables.x.where(...)) in a Svelte component without an ancestor that called createSpacetimeDBProvider(builder); also when the hook runs outside synchronous component init (module scope, onMount, after an await), where getContext cannot find the key.

Common situations: Table-reading components used across routes while the provider exists on only one; refactor moved the provider call deeper into the tree; SvelteKit prerender or HMR paths mounting consumers without the layout that owns the provider.

Related errors


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

Appendix: source

Thrown at crates/bindings-typescript/src/svelte/useTable.ts:63

 *
 * @param query - A query builder expression (table reference or filtered query).
 * @param callbacks - Optional callbacks for row insert, delete, and update events.
 * @returns A tuple of [rows, isReady].
 */
export function useTable<TableDef extends UntypedTableDef>(
  query: Query<TableDef>,
  callbacks?: UseTableCallbacks<Prettify<RowType<TableDef>>>
): [Readable<readonly Prettify<RowType<TableDef>>[]>, Readable<boolean>] {
  type Row = RowType<TableDef>;
  const accessorName = getQueryAccessorName(query);
  const whereExpr = getQueryWhereClause(query);
  const querySql = toSql(query);

  let connectionStore;
  try {
    connectionStore = useSpacetimeDB();
  } catch {
    throw new Error(
      'Could not find SpacetimeDB client! Did you forget to call ' +
        '`createSpacetimeDBProvider`? `useTable` must be used in a Svelte component tree ' +
        'under a component that called `createSpacetimeDBProvider`.'
    );
  }

  const rows = writable<readonly Prettify<Row>[]>([]);
  const isReady = writable(false);

  let latestTransactionEvent: any = null;
  let unsubscribeFromTable: (() => void) | null = null;
  let subscriptionHandle: { unsubscribe: () => void } | null = null;

  const computeFilteredRows = (): readonly Prettify<Row>[] => {
    const state = get(connectionStore);
    const connection = state.getConnection();
    if (!connection) return [];

View on GitHub (pinned to 6dee26c6ef)