clockworklabs/SpacetimeDB · error · TypeError
multiple schemas are not supported
Error message
multiple schemas are not supported
What it means
Every export object created by a schema (reducers, procedures, views, HTTP handlers) carries a hidden `[exportContext]` referring to the SchemaInner it was built from. Before registering an export, `checkExportContext` verifies the export's context is the same schema doing the registration; mixing exports from two different `schema()` instances throws 'multiple schemas are not supported'. A module must be built against exactly one schema instance.
Solutions
- Create ALL exports from the single schema instance whose entry object you pass to `schema()` — import that instance everywhere instead of constructing a second one.
- If a submodule library defines tables/reducers, follow the submodule pattern: import the library as a namespace (`import * as lib from 'lib'`) and pass the namespace object as a schema entry, so the library's schema is nested rather than mixed.
- After test/HMR reloads, rebuild exports fresh alongside the fresh schema instead of reusing cached export objects.
Example fix
// before
// lib.ts
export const libSchema = schema({ t1 });
export const libReducer = libSchema.reducer(...);
// app.ts — different schema instance registering libReducer
export default schema({ t2, libReducer }); // TypeError: multiple schemas are not supported
// after — nest the library as a submodule namespace
import * as lib from './lib';
export default schema({ t2, lib }); Defensive patterns
Strategy: type-guard
Validate before calling
// Create all exports from one shared schema instance.
// schemaInstance.ts
import { schema } from '...';
export const appSchema = schema({ /* tables */ });
// everywhere else: import { appSchema } from './schemaInstance'; Type guard
// If you can compare against the schema instance:
function belongsToSchema(exp: unknown, schemaInstance: unknown): boolean {
return typeof exp === 'function' || typeof exp === 'object'; // real check needs the hidden [exportContext]; proxy it by tracking creators
}
// Practical guard: maintain a Set of exports created via appSchema.* and check membership. Prevention
- Construct `schema()` exactly once per module and export that instance for everyone to build reducers/handlers with.
- Integrate libraries via namespace-import submodule entries, not by re-exporting their functions.
- After HMR/test reloads, rebuild exports together with the schema rather than caching them.
When it happens
Trigger: Calling `schema({...})` twice (e.g. in two files) and exporting functions created from instance A while instance B registers the module; a library submodule creating its exports against its own `schema()` call and the app re-exporting them; HMR/test setups that rebuild the schema but reuse stale export objects.
Common situations: Shared 'base' module that defines `export const baseSchema = schema({...})` plus its reducers, later imported into an app with its own `schema()`; accidentally importing the schema from a package's entry and also constructing one locally; hot-reload keeping old module objects alive.
Related errors
- schema entry ' ' looks like a default import; use `import *…
- exporting something that is not a spacetime export
- HTTP handler ' ' was exported more than once
- HTTP route for path ' ' refers to a handler that was not…
- invalid sequence type
AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-08-20).
Data as JSON: /api/errors/608354caffe42ca9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/bindings-typescript/src/server/schema.ts:729
export const exportContext = Symbol('SpacetimeDB.exportContext');
export interface ModuleExport {
[registerExport](ctx: SchemaInner, exportName: string): void;
[exportContext]?: SchemaInner;
}
function isModuleExport(x: unknown): x is ModuleExport {
return (
(typeof x === 'function' || typeof x === 'object') &&
x !== null &&
registerExport in x
);
}
/** Verify that the ModuleContext that `exp` comes from is the same as `schema` */
function checkExportContext(exp: ModuleExport, schema: SchemaInner) {
if (exp[exportContext] != null && exp[exportContext] !== schema) {
throw new TypeError('multiple schemas are not supported');
}
}
/**
* Extracts the inferred schema type from a Schema instance
*/
export type InferSchema<SchemaDef extends Schema<any>> =
SchemaDef extends Schema<infer S> ? S : never;
/**
* Creates a schema from table definitions
* @param handles - Array of table handles created by table() function
* @returns ColumnBuilder representing the complete database schema
* @example
* ```ts
* const spacetimedb = schema({
* user: table({}, userType),
* post: table({}, postType)View on GitHub (pinned to eddf9f5014)