mastra-ai/mastra · error · Error

Schedule ${id} not found

Error message

Schedule ${id} not found

What it means

InMemoryScheduleStorage.updateSchedule() throws when no schedule with the given id exists in the store. The in-memory implementation has no upsert mode; updates apply only to existing schedules so callers can distinguish typos/deleted ids from successful patches.

Source

Thrown at packages/core/src/storage/domains/schedules/inmemory.ts:77

    return rows.map(cloneRow);
  }

  async listDueSchedules(now: number, limit?: number): Promise<Schedule[]> {
    const due: Schedule[] = [];
    for (const row of this.db.schedules.values()) {
      if (row.status === 'active' && row.nextFireAt <= now) {
        due.push(row);
      }
    }
    due.sort((a, b) => a.nextFireAt - b.nextFireAt);
    const cap = limit ?? due.length;
    return due.slice(0, cap).map(cloneRow);
  }

  async updateSchedule(id: string, patch: ScheduleUpdate): Promise<Schedule> {
    const existing = this.db.schedules.get(id);
    if (!existing) {
      throw new Error(`Schedule ${id} not found`);
    }
    const updated: Schedule = {
      ...existing,
      ...patch,
      target: patch.target !== undefined ? patch.target : existing.target,
      metadata: patch.metadata !== undefined ? patch.metadata : existing.metadata,
      updatedAt: Date.now(),
    };
    const stored = clone(updated);
    this.db.schedules.set(id, stored);
    return cloneRow(stored);
  }

  async updateScheduleNextFire(
    id: string,
    expectedNextFireAt: number,
    newNextFireAt: number,
    lastFireAt: number,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Create the schedule before updating it, or switch the flow to createSchedule on absence.
  2. Look up the schedule first (listSchedules / getSchedule) and handle the missing case explicitly.
  3. Ensure the same storage instance is used for create and update (in-memory stores don't share state).
  4. Log/inspect the exact id being passed; fix typos or stale serialized ids.

Example fix

// before
await storage.schedules.updateSchedule('nightly-job', { enabled: false });
// after
try {
  await storage.schedules.updateSchedule('nightly-job', { enabled: false });
} catch {
  await storage.schedules.createSchedule({ id: 'nightly-job', enabled: false, ...baseDef });
}
Defensive patterns

Strategy: try-catch

Validate before calling

const all = await storage.schedules.listSchedules();
if (!all.schedules?.some(s => s.id === id)) {
  throw new Error(`cannot update: schedule ${id} does not exist`);
}

Type guard

function findSchedule(schedules: { id: string }[], id: string): { id: string } | undefined {
  return schedules.find(s => s.id === id);
}

Try / catch

try {
  return await storage.schedules.updateSchedule(id, patch);
} catch (e) {
  if (e instanceof Error && e.message === `Schedule ${id} not found`) {
    throw new Error(`Schedule ${id} was never created in this storage instance; call createSchedule first`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling updateSchedule('sched-1', { enabled: false }) after the schedule was never created, was deleted, or the store was cleared; using an id from a different storage instance or an old serialized reference.

Common situations: Disabling a schedule that a previous process run created but this run didn't; test teardown clearing schedules while a handler still holds the id; id typos or truncated ids from logs.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/d77ebaec4f36de7c. Report an issue: GitHub.