clockworklabs/SpacetimeDB · error · TypeError

There is already a reducer, procedure, or view with the name

Error message

There is already a reducer, procedure, or view with the name '${name}'

What it means

All callable module functions — reducers, procedures, and views — share one namespace per schema. `SchemaInner.defineFunction` records each export name in `existingFunctions` and throws this error on the second registration of the same name. It fires during export registration (module build/publish), naming the offending export.

Solutions

  1. Rename one of the two functions named in the error message so every reducer/procedure/view export name is unique in the module.
  2. If a submodule function collides, re-export it under an alias: `export { tick as schedulerTick } from './scheduler';`.
  3. Run `spacetime build` locally before publish; the error is deterministic and points at the exact name.
  4. Add a lint/CI check that collects all function export names of the entry module and fails on duplicates.

Example fix

// before
export const transfer = spacetimedb.reducer(...);
export const transfer = spacetimedb.view(...); // duplicate name

// after
export const transfer = spacetimedb.reducer(...);
export const transferView = spacetimedb.view(...);
Defensive patterns

Strategy: validation

Validate before calling

// Dev-time: assert all function exports in the entry are uniquely named.
const fnNames = new Set<string>();
function defineFn(name: string) {
  if (fnNames.has(name)) throw new Error(`duplicate function export: ${name}`);
  fnNames.add(name);
}
// call defineFn('transfer') wherever you create reducers/procedures/views

Prevention

When it happens

Trigger: Two exported functions with the same name in one module (e.g. `transfer` reducer and `transfer` view); re-exporting a function from a submodule under a name that already exists in the entry module; a rename that leaves an old and a new export both present.

Common situations: Merging two feature modules that both define `init` or `tick`; copy-pasting a reducer and renaming the const but not consistently; barrel re-exports (`export * from './a'; export * from './b';`) where both files export the same name — TypeScript usually flags ambiguous star re-exports, but explicit aliases slip through.

Related errors


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

Appendix: source

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

   * Maps reducer/procedure export objects to their source names.
   * Used for resolving scheduled table targets.
   */
  functionExports: Map<UntypedScheduledFunctionExport, string> = new Map();
  tableSourceNames: Map<UntypedTableSchema, string[]> = new Map();
  httpHandlerExports: Map<HttpHandlerExport<UntypedSchemaDef>, string> =
    new Map();
  pendingSchedules: PendingSchedule[] = [];
  pendingHttpRoutes: PendingHttpRoute[] = [];
  submoduleDispatchInfos: SubmoduleDispatchInfo[] = [];

  constructor(getSchemaType: (ctx: SchemaInner<S>) => S) {
    super();
    this.schemaType = getSchemaType(this);
  }

  defineFunction(name: string) {
    if (this.existingFunctions.has(name)) {
      throw new TypeError(
        `There is already a reducer, procedure, or view with the name '${name}'`
      );
    }
    this.existingFunctions.add(name);
  }

  defineHttpHandler(name: string) {
    if (this.existingHttpHandlers.has(name)) {
      throw new TypeError(
        `There is already an HTTP handler with the name '${name}'`
      );
    }
    this.existingHttpHandlers.add(name);
  }

  resolveSchedules() {
    if (this.schedulesResolved) {
      return;

View on GitHub (pinned to eddf9f5014)