clockworklabs/SpacetimeDB · error · TypeError

schema entry ' ' looks like a default import; use `import *…

Error message

schema entry '${accName}' looks like a default import; use `import * as ${accName} from '...'` so the submodule can see the library's named reducer exports.

What it means

Entries in the object passed to `schema({...})` must be tables or submodule namespace objects. If an entry is itself a `Schema` instance (`entry instanceof Schema`), the usual cause is a default import of a library module (`import Lib from 'lib'` yields the schema) used directly as an entry. The error message is prescriptive: re-import as a namespace so the schema can see and register the library's named reducer exports.

Solutions

  1. Change to a namespace import: `import * as scheduledLib from '../lib';` and keep `schema({ scheduledLib })`.
  2. Make sure the library file has named exports for its reducers/tables; the schema entry must be the namespace object, not the library's default export.
  3. If the entry should be a table, pass the `table()` handle directly instead of the module/schema object.

Example fix

// before
import scheduledLib from '../lib'; // default import = Schema instance
export default schema({ users, scheduledLib }); // TypeError

// after
import * as scheduledLib from '../lib';
export default schema({ users, scheduledLib });
Defensive patterns

Strategy: type-guard

Validate before calling

// Normalize schema entries: reject Schema instances before calling schema().
import { Schema } from '...';
function assertEntries(entries: Record<string, unknown>) {
  for (const [name, entry] of Object.entries(entries)) {
    if (entry instanceof Schema) throw new Error(`${name} is a Schema; use a namespace import`);
  }
}

Type guard

function isSchemaInstance(x: unknown): x is Schema { return x instanceof Schema; }

Prevention

When it happens

Trigger: `import scheduledLib from '../lib'; export default schema({ scheduledLib })` where the library's default export is a `Schema`; mixing up the library's default export (schema) with its namespace (tables + reducers); refactoring an import from `import * as x` to `import x` during a cleanup.

Common situations: Integrating a shared spacetime library as a submodule; auto-fix/'add missing imports' switching to a default import; copy-pasting integration snippets with the wrong import style.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-08-20). Data as JSON: /api/errors/92f8213c4a1b36d3. Report an issue: GitHub.

Appendix: source

Thrown at crates/bindings-typescript/src/server/schema.ts:855

  const H extends Record<string, SchemaEntry>,
  const E extends EnvironmentSchema = {},
>(
  entries: H,
  moduleSettings?: ModuleSettings<E>
): Schema<SchemaDefForEntries<H> & { env: E }> {
  const ctx = new SchemaInner<SchemaDefForEntries<H> & { env: E }>(ctx => {
    ctx.moduleDef.environment = environmentDeclarations(
      moduleSettings?.env ?? {}
    );
    // Apply module settings.
    if (moduleSettings?.CASE_CONVERSION_POLICY != null) {
      ctx.setCaseConversionPolicy(moduleSettings.CASE_CONVERSION_POLICY);
    }

    const tableSchemas: Record<string, UntypedTableDef> = {};
    for (const [accName, entry] of Object.entries(entries)) {
      if (entry instanceof Schema) {
        throw new TypeError(
          `schema entry '${accName}' looks like a default import; use \`import * as ${accName} from '...'\` so the submodule can see the library's named reducer exports.`
        );
      }
      if (isSubmoduleNamespace(entry)) {
        const { rawDef, dispatch } =
          entry.default.buildSubmoduleDispatch(entry);
        dispatch.namespace = accName;
        ctx.addSubmodule({ namespace: accName, module: rawDef });
        ctx.submoduleDispatchInfos.push(dispatch);
        continue;
      }
      if (!isUntypedTableSchema(entry)) {
        throw new TypeError(
          `schema entry '${accName}' must be a table or a submodule namespace object`
        );
      }

      const table = entry;

View on GitHub (pinned to eddf9f5014)