mastra-ai/mastra · error · HTTPException

Schedule not found

Error message

Schedule not found

What it means

loadSchedule resolves a schedule by id via mastra.schedules.get and throws a clean HTTP 404 'Schedule not found' when no row exists, so GET/UPDATE/DELETE/PAUSE/RESUME/RUN schedule routes surface a proper 404 instead of an internal service error.

Source

Thrown at packages/server/src/server/handlers/schedules.ts:85

async function hydrateScheduleResponse(
  mastra: Mastra,
  schedule: AnySchedule,
): Promise<AgentSchedule | (WorkflowSchedule & { lastRun?: RunSummary })> {
  if (!schedule.workflowId || !schedule.lastRunId) {
    return schedule;
  }
  const lastRun = await fetchRunSummary(mastra, schedule.workflowId, schedule.lastRunId);
  return lastRun ? { ...schedule, lastRun } : schedule;
}

/**
 * Resolve a schedule by id via `mastra.schedules`. Returns 404 for missing
 * rows so handlers surface a clean HTTP error instead of a service error.
 */
async function loadSchedule(mastra: Mastra, scheduleId: string): Promise<AnySchedule> {
  const schedule = await mastra.schedules.get(scheduleId);
  if (!schedule) {
    throw new HTTPException(404, { message: 'Schedule not found' });
  }
  return schedule;
}

export const LIST_SCHEDULES_ROUTE = createRoute({
  method: 'GET',
  path: '/schedules',
  responseType: 'json' as const,
  queryParamSchema: listSchedulesQuerySchema,
  responseSchema: listSchedulesResponseSchema,
  summary: 'List schedules',
  description:
    'Returns all schedules — agent schedules and workflow schedules — optionally filtered by agentId, workflowId, or status. Agent schedules can additionally be filtered by threadId, resourceId, or name.',
  tags: ['Schedules'],
  requiresAuth: true,
  handler: async ({ mastra, agentId, workflowId, status, threadId, resourceId, name }) => {
    const schedulesStore = await mastra.getStorage()?.getStore('schedules');
    if (!schedulesStore) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. List schedules (GET /api/schedules) and use an id from the current list.
  2. Verify the schedules storage backend the server reads from is the one your schedule was created in.
  3. Create the schedule again if it was deleted (mastra.schedules.create or the POST route).

Example fix

// before
await client.getSchedule('nightly-job') // table was wiped
// after
const { schedules } = await client.getSchedules()
const s = schedules.find(s => s.id === 'nightly-job')
if (s) await client.getSchedule(s.id)
Defensive patterns

Strategy: try-catch

Validate before calling

const schedules = await client.getSchedules();
if (!schedules.some(s => s.id === scheduleId)) {
  return null; // schedule absent; skip GET/UPDATE/DELETE
}

Try / catch

try {
  return await client.getSchedule(scheduleId);
} catch (e) {
  if (isHttpError(e, 404)) return null;
  throw e;
}

Prevention

When it happens

Trigger: Any schedule route taking :scheduleId (GET one, PUT update, DELETE, pause, resume, run) with an id that has no corresponding row in the schedules storage.

Common situations: Client kept a schedule id after the schedules table was reset/migrated; typo'd or URL-encoded id mismatch; schedule deleted by another process between listing and acting on it.

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/b589cf56393d91f6. Report an issue: GitHub.