mastra-ai/mastra · error · Error

Workflow "${params.id}" declares an array of schedules but o

Error message

Workflow "${params.id}" declares an array of schedules but one entry is missing the required `id` field. Every entry in a schedule array must have a unique stable id.

What it means

When defining a workflow with `schedule` given as an array, every entry must carry its own stable `id`. A plain `Error` is thrown during workflow construction because one of the array entries lacks an `id`. Single schedule objects are exempt (the workflow id identifies them), but arrays need per-entry ids so each schedule can be uniquely registered, updated, and cancelled.

Source

Thrown at packages/core/src/workflows/evented/workflow.ts:1638

  TStateSchema extends PublicSchema<any> | undefined = undefined,
  TSteps extends Step<string, any, any, any, any, any, EventedEngineType>[] = Step<
    string,
    any,
    any,
    any,
    any,
    any,
    EventedEngineType
  >[],
  TRequestContextSchema extends PublicSchema<any> | undefined = undefined,
>(params: CreateWorkflowParams<TWorkflowId, TStateSchema, TInputSchema, TOutputSchema, TSteps, TRequestContextSchema>) {
  if (params.schedule) {
    const schedules = Array.isArray(params.schedule) ? params.schedule : [params.schedule];
    if (Array.isArray(params.schedule)) {
      const seenIds = new Set<string>();
      for (const entry of schedules) {
        if (!entry.id) {
          throw new Error(
            `Workflow "${params.id}" declares an array of schedules but one entry is missing the required \`id\` field. Every entry in a schedule array must have a unique stable id.`,
          );
        }
        if (seenIds.has(entry.id)) {
          throw new Error(`Workflow "${params.id}" declares duplicate schedule id "${entry.id}".`);
        }
        seenIds.add(entry.id);
      }
    }
    for (const entry of schedules) {
      validateCron(entry.cron, entry.timezone);
    }
  }
  const eventProcessor = new WorkflowEventProcessor({ mastra: params.mastra! });
  const executionEngine = new EventedExecutionEngine({
    mastra: params.mastra!,
    eventProcessor,
    options: {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Add a unique, stable `id` string to every entry in the schedule array.
  2. If there is only one schedule, pass a single schedule object instead of an array to avoid the id requirement.
  3. Validate schedule entries at startup (map over the array and assert each has a truthy id) before constructing the workflow.

Example fix

// before
new Workflow({ id: 'report', schedule: [{ cron: '0 * * * *' }, { cron: '0 12 * * *' }] });

// after
new Workflow({ id: 'report', schedule: [
  { id: 'hourly', cron: '0 * * * *' },
  { id: 'noon', cron: '0 12 * * *' },
] });
Defensive patterns

Strategy: validation

Validate before calling

function assertScheduleIds(workflowId: string, schedule: unknown): void {
  const entries = Array.isArray(schedule) ? schedule : [schedule];
  for (const [i, e] of entries.entries()) {
    if (typeof e !== 'object' || e === null || !('id' in e) || typeof (e as any).id !== 'string' || !(e as any).id) {
      throw new Error(`Workflow "${workflowId}" schedule entry ${i} is missing a required string "id"`);
    }
  }
}
assertScheduleIds('report', schedule); // call before new Workflow(...)

Type guard

function hasScheduleId(e: unknown): e is { id: string; cron?: string; timezone?: string } {
  return typeof e === 'object' && e !== null && typeof (e as any).id === 'string' && (e as any).id.length > 0;
}

Prevention

When it happens

Trigger: Calling `new Workflow({ id, schedule: [ { cron: '...' }, ... ] })` (or passing schedule through the params object) where at least one array element has no `id` property or an empty/falsy id (workflow.ts:1633-1646).

Common situations: Converting a single-schedule workflow to multiple schedules by wrapping the object in an array without adding ids; copy-pasting schedule entries and dropping the id; generating schedules dynamically and omitting the field.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/1208175de2f966d6. Report an issue: GitHub.