{"record":{"id":"608354caffe42ca9","repo":"clockworklabs/SpacetimeDB","slug":"multiple-schemas-are-not-supported","errorCode":null,"errorMessage":"multiple schemas are not supported","messagePattern":"multiple schemas are not supported","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/server/schema.ts","lineNumber":729,"sourceCode":"export const exportContext = Symbol('SpacetimeDB.exportContext');\n\nexport interface ModuleExport {\n  [registerExport](ctx: SchemaInner, exportName: string): void;\n  [exportContext]?: SchemaInner;\n}\n\nfunction isModuleExport(x: unknown): x is ModuleExport {\n  return (\n    (typeof x === 'function' || typeof x === 'object') &&\n    x !== null &&\n    registerExport in x\n  );\n}\n\n/** Verify that the ModuleContext that `exp` comes from is the same as `schema` */\nfunction checkExportContext(exp: ModuleExport, schema: SchemaInner) {\n  if (exp[exportContext] != null && exp[exportContext] !== schema) {\n    throw new TypeError('multiple schemas are not supported');\n  }\n}\n\n/**\n * Extracts the inferred schema type from a Schema instance\n */\nexport type InferSchema<SchemaDef extends Schema<any>> =\n  SchemaDef extends Schema<infer S> ? S : never;\n\n/**\n * Creates a schema from table definitions\n * @param handles - Array of table handles created by table() function\n * @returns ColumnBuilder representing the complete database schema\n * @example\n * ```ts\n * const spacetimedb = schema({\n *   user: table({}, userType),\n *   post: table({}, postType)","sourceCodeStart":711,"sourceCodeEnd":747,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/eddf9f5014579a50d4b67630e28b6e15cad9c4af/crates/bindings-typescript/src/server/schema.ts#L711-L747","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n// lib.ts\nexport const libSchema = schema({ t1 });\nexport const libReducer = libSchema.reducer(...);\n// app.ts — different schema instance registering libReducer\nexport default schema({ t2, libReducer }); // TypeError: multiple schemas are not supported\n\n// after — nest the library as a submodule namespace\nimport * as lib from './lib';\nexport default schema({ t2, lib });","handlingStrategy":"type-guard","validationCode":"// Create all exports from one shared schema instance.\n// schemaInstance.ts\nimport { schema } from '...';\nexport const appSchema = schema({ /* tables */ });\n// everywhere else: import { appSchema } from './schemaInstance';","typeGuard":"// If you can compare against the schema instance:\nfunction belongsToSchema(exp: unknown, schemaInstance: unknown): boolean {\n  return typeof exp === 'function' || typeof exp === 'object'; // real check needs the hidden [exportContext]; proxy it by tracking creators\n}\n// Practical guard: maintain a Set of exports created via appSchema.* and check membership.","tryCatchPattern":null,"preventionTips":["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."],"tags":["schema","exports","modules","build-time","spacetimedb"],"backgroundTag":"multiple-schema-instances","analyzedSha":"eddf9f5014579a50d4b67630e28b6e15cad9c4af","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}