mastra-ai/mastra · error · MastraError

SCHEDULES_NO_SCHEDULES_STORAGE

SCHEDULES_NO_SCHEDULES_STORAGE

Error message

Schedules require a storage adapter that implements the schedules domain.

What it means

The `Schedules` service (`#getStore` in packages/core/src/schedules/schedules.ts:236) requires a storage adapter that implements the schedules domain. It fetches the Mastra storage instance and asks it for the `schedules` store; if no storage is configured or the adapter has no schedules domain, `SCHEDULES_NO_SCHEDULES_STORAGE` is thrown because schedule rows cannot be persisted.

Source

Thrown at packages/core/src/schedules/schedules.ts:236

 * agent (via signal or `agent.generate`), `type: 'workflow'` rows start a
 * workflow run. This class is a typed projection over `SchedulesStorage`
 * that knows how to build targets and surface flat
 * {@link AgentSchedule} / {@link WorkflowSchedule} views.
 *
 * Use via `mastra.schedules` (the canonical CRUD surface).
 */
export class Schedules {
  #mastra: Mastra;

  constructor(mastra: Mastra) {
    this.#mastra = mastra;
  }

  async #getStore() {
    const storage = this.#mastra.getStorage();
    const store = await storage?.getStore('schedules');
    if (!store) {
      throw new MastraError({
        id: 'SCHEDULES_NO_SCHEDULES_STORAGE',
        domain: ErrorDomain.AGENT,
        category: ErrorCategory.USER,
        text: 'Schedules require a storage adapter that implements the schedules domain.',
      });
    }
    return store;
  }

  /**
   * Resolve a caller-supplied id to a stored row. An id is first looked up
   * verbatim (covering `agent_`, `schedule_`, `wf_`, and legacy `hb_` ids);
   * when that misses, a bare caller id is canonicalized to `agent_<slug>` to
   * match what agent-schedule `create` persisted.
   */
  async #load(id: string): Promise<Schedule | null> {
    const store = await this.#getStore();
    const trimmed = id.trim();

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Configure a storage adapter that implements the schedules domain, e.g. `new Mastra({ storage: new LibSQLStore({ url: 'file:./mastra.db' }) })` (or your preferred supported store), and rebuild.
  2. Upgrade the storage package (`@mastra/libsql`, `@mastra/pg`, etc.) to a version that implements the schedules domain.
  3. Verify with `await storage.getStore('schedules')` that the store resolves before using schedules.

Example fix

// before
export const mastra = new Mastra({ agents }); // no storage

// after
import { LibSQLStore } from '@mastra/libsql';
export const mastra = new Mastra({
  agents,
  storage: new LibSQLStore({ url: 'file:./mastra.db' }),
});
Defensive patterns

Strategy: validation

Validate before calling

async function assertSchedulesStorage(mastra) {
  const storage = mastra.getStorage();
  if (!storage) throw new Error('Mastra instance has no storage configured');
  const store = await storage.getStore('schedules');
  if (!store) throw new Error('Storage adapter does not implement the schedules domain');
}

Try / catch

try {
  await schedules.create(input);
} catch (e) {
  if (e instanceof MastraError && e.id === 'SCHEDULES_NO_SCHEDULES_STORAGE') {
    console.error('Configure a storage adapter that implements the schedules domain');
  } else throw e;
}

Prevention

When it happens

Trigger: Any schedules API call (`create`, `list`, `get`, `update`, `delete`, `pause`, `resume`) when `Mastra` was constructed without `storage`, or with a storage adapter whose `getStore('schedules')` returns nothing (adapter does not implement the schedules domain).

Common situations: Omitting the `storage` option in `new Mastra({...})` in dev; using an older or minimal storage adapter (e.g. libsql/in-memory variant) that predates or omits the schedules domain; upgrading Mastra and calling the new schedules API against a pre-existing storage config; unit tests instantiating Mastra without storage.

Related errors


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