clockworklabs/SpacetimeDB · error · TypeError
Table defines a schedule, but it seems like the associated…
Error message
Table ${tableName} defines a schedule, but it seems like the associated function was not exported. What it means
A schedule needs the function that will run when rows mature. Resolution looks the reducer/procedure up via `this.functionExports.get(reducer())`; if the function referenced by the schedule was never exported from the module, `functionName` is undefined and the build fails with 'the associated function was not exported'. The scheduled function must be a module export registered in the same schema.
Solutions
- Export the scheduled function from the module: `export const processMessage = spacetimedb.reducer({ onSchedule: scheduledMessages }, ...)`.
- With the modern `onSchedule` API the function and schedule are declared together — prefer it over the legacy `schedule()` API to avoid identity mismatches.
- If using a factory, call it once, store the result, and use that same object for both the export and the schedule.
Example fix
// before (legacy style)
const processMessage = () => spacetimedb.reducer(...);
const messages = table({ schedule: scheduleRef }, row); // fn never exported
// after
export const processMessage = spacetimedb.reducer(
{ onSchedule: scheduledMessages },
{ scheduledMessage: scheduledMessages.rowType },
(ctx, { scheduledMessage }) => {}
); Defensive patterns
Strategy: validation
Validate before calling
// With factories, register the exact object you export.
const registeredFns = new Set<Function>();
function exportOnce<T extends Function>(name: string, fn: T): T {
if (registeredFns.has(fn)) throw new Error(`${name} must be exported exactly once`);
registeredFns.add(fn);
return fn;
} Prevention
- Prefer the modern `onSchedule` API, which declares function and table together.
- Always `export const` the scheduled function in the same file where it is defined.
- Call reducer factories exactly once and reuse the returned export object.
When it happens
Trigger: Using the legacy `schedule(fn)` table API where `fn` is not exported; defining the scheduled reducer but forgetting `export const ...`; the schedule referencing a function object different from the one actually exported (two closures created by a factory).
Common situations: Factory-created reducers (`const make = () => spacetimedb.reducer(...)`): the factory is called twice — once for the export, once for the schedule — so identity lookup fails; refactors that remove an export but leave a legacy schedule pointing at it.
Related errors
- Table defines multiple schedules: and . A schedule table…
- There is already a reducer, procedure, or view with the name
- 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…
AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-08-20).
Data as JSON: /api/errors/e1965c6b5706be29.
Report an issue: GitHub.
Appendix: source
Thrown at crates/bindings-typescript/src/server/schema.ts:190
'Schedule target table is not part of this schema.'
);
}
const scheduleAtCol = knownScheduleAtCol ?? table.scheduleAtCol;
if (scheduleAtCol === undefined) {
throw new TypeError(
`Table ${tableName} defines a schedule, but it does not have a ScheduleAt column.`
);
}
const functionName =
knownFunctionName ??
(reducer === undefined
? undefined
: this.functionExports.get(reducer()));
if (functionName === undefined) {
const msg = `Table ${tableName} defines a schedule, but it seems like the associated function was not exported.`;
throw new TypeError(msg);
}
const existingFunctionName = scheduledTables.get(tableName);
if (existingFunctionName !== undefined) {
throw new TypeError(
`Table ${tableName} defines multiple schedules: ${existingFunctionName} and ${functionName}. A schedule table can only be used by one reducer or procedure.`
);
}
scheduledTables.set(tableName, functionName);
this.moduleDef.schedules.push({
sourceName: undefined,
tableName,
scheduleAtCol,
functionName,
});
}
}
resolveHttpRoutes() {View on GitHub (pinned to eddf9f5014)