mastra-ai/mastra · error · Error

Workflow "${params.id}" declares duplicate schedule id "${en

Error message

Workflow "${params.id}" declares duplicate schedule id "${entry.id}".

What it means

When a workflow's `schedule` is an array, ids must be unique across entries; a duplicate id is detected with a `seenIds` Set and a plain `Error` is thrown. Duplicate ids would make it ambiguous which cron/timezone definition a registration refers to, breaking schedule updates and cancellation.

Source

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

    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: {
      validateInputs: params.options?.validateInputs ?? true,
      shouldPersistSnapshot: params.options?.shouldPersistSnapshot ?? (() => true),
      pruneSnapshot: params.options?.pruneSnapshot,
      tracingPolicy: params.options?.tracingPolicy,
      onStart: params.options?.onStart,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Rename one of the conflicting entries so every id in the array is unique.
  2. Generate deterministic distinct ids programmatically when building schedules dynamically (e.g. suffix by index or purpose).
  3. Pre-validate the array with a Set-based uniqueness check before constructing the workflow to fail fast with a clearer message.

Example fix

// before
schedule: [{ id: 'sync', cron: '0 * * * *' }, { id: 'sync', cron: '*/5 * * * *' }]

// after
schedule: [{ id: 'sync-hourly', cron: '0 * * * *' }, { id: 'sync-every-5m', cron: '*/5 * * * *' }]
Defensive patterns

Strategy: validation

Validate before calling

function assertUniqueScheduleIds(workflowId: string, schedule: unknown): void {
  if (!Array.isArray(schedule)) return;
  const seen = new Set<string>();
  for (const e of schedule) {
    if (seen.has(e.id)) throw new Error(`Workflow "${workflowId}" has duplicate schedule id "${e.id}"`);
    seen.add(e.id);
  }
}
assertUniqueScheduleIds('report', schedule);

Type guard

function idsAreUnique(entries: { id: string }[]): entries is { id: string }[] {
  return new Set(entries.map(e => e.id)).size === entries.length;
}

Prevention

When it happens

Trigger: `new Workflow({ id, schedule: [ { id: 'a', cron }, { id: 'a', cron } ] })` — the second entry's id is already in `seenIds` (workflow.ts:1641-1649).

Common situations: Copy-pasting a schedule entry and forgetting to change the id; merging schedule lists from config or environment where entries share defaults; template code that clones entries.

Related errors


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