clockworklabs/SpacetimeDB · error · Error
Could not find SpacetimeDB client! Did you forget to add a…
Error message
Could not find SpacetimeDB client! Did you forget to add a `SpacetimeDBProvider`? `useTable` must be used in the SolidJS component tree under a `SpacetimeDBProvider` component.
What it means
useTable in the Solid bindings calls useSpacetimeDB() inside a try/catch; when the context lookup fails because there is no SpacetimeDBProvider above, the original error is discarded and this dedicated message is thrown instead. The subscription machinery cannot even start because there is no connection to subscribe with, so the hook fails immediately at call time, before the enabled() gate is consulted.
Solutions
- Add <SpacetimeDBProvider connectionBuilder={builder}> above the component calling useTable
- Confirm you used the Solid bindings' own provider, not the React or Vue one
- In tests, render the component inside the provider before asserting rows
- Check that the useTable import comes from the solid entry point and that the provider wraps the whole subtree
Example fix
// before
export default function App() {
const [players] = useTable(tables.player); // throws: no provider above
return <For each={players}>{(p) => <div>{p.name}</div>}</For>;
}
// after
import { SpacetimeDBProvider } from '@clockworklabs/spacetime-db-solid';
export default function App() {
return (
<SpacetimeDBProvider connectionBuilder={builder}>
<Players />
</SpacetimeDBProvider>
);
} Defensive patterns
Strategy: try-catch
Validate before calling
import { useContext } from 'solid-js';
import { SpacetimeDBContext } from './solid/useSpacetimeDB';
// gate hook usage on provider presence
const canUseTables = () => useContext(SpacetimeDBContext) !== undefined; Try / catch
// useTable throws during render; wrap consumers in Solid's ErrorBoundary
<ErrorBoundary fallback={(err) => <div>{String(err)}</div>}>
<TableComponent />
</ErrorBoundary> Prevention
- Always mount table components through a shared layout that contains the provider
- Smoke-test each table component inside the provider in unit tests
- Import provider and hooks from the same bindings package
When it happens
Trigger: Calling useTable(tables.x) or useTable(query, { enabled }) from the Solid bindings inside a component that lacks a <SpacetimeDBProvider connectionBuilder={...}> ancestor. Even conditionally enabled queries throw, because the provider check runs before the enabled() check.
Common situations: Provider added to a subset of routes while a shared component uses useTable; tests rendering the table component in isolation; porting from React where the provider API differs; provider placed after (below) the consumer in the tree.
Related errors
- useSpacetimeDB must be used within a SpacetimeDBProvider…
- Could not find SpacetimeDB client! Did you forget to call…
- Could not find SpacetimeDB client! Did you forget to add a…
- useSpacetimeDB must be used within a component that called…
- useSpacetimeDB must be used within a SpacetimeDBProvider…
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/b33c7b2eb89a18ab.
Report an issue: GitHub.
Appendix: source
Thrown at crates/bindings-typescript/src/solid/useTable.ts:76
* );
* ```
*/
export function useTable<TableDef extends UntypedTableDef>(
query: () => Query<TableDef>,
callbacks?: UseTableCallbacks<Prettify<RowType<TableDef>>>
): [readonly Prettify<RowType<TableDef>>[], () => boolean] {
type UseTableRowType = RowType<TableDef>;
const enabled = callbacks?.enabled ?? (() => true);
const q = createMemo(query);
const accessorName = createMemo(() => getQueryAccessorName(q()));
const whereExpr = createMemo(() => getQueryWhereClause(q()));
const querySql = createMemo(() => toSql(q()));
let connectionState: import('./connection_state').ConnectionState;
try {
connectionState = useSpacetimeDB();
} catch {
throw new Error(
'Could not find SpacetimeDB client! Did you forget to add a ' +
'`SpacetimeDBProvider`? `useTable` must be used in the SolidJS component tree ' +
'under a `SpacetimeDBProvider` component.'
);
}
const [rows, setRows] = createStore<readonly Prettify<UseTableRowType>[]>([]);
let latestTransactionEventId: string | null = null;
const computeSnapshot = (): readonly Prettify<UseTableRowType>[] => {
if (!enabled()) {
return [];
}
const connection = connectionState.getConnection();
if (!connection) {
return [];View on GitHub (pinned to 6dee26c6ef)