mastra-ai/mastra · error · Error

Invalid cron expression: expected a non-empty cron string (e

Error message

Invalid cron expression: expected a non-empty cron string (e.g. "0 * * * *"), but received ${cron === undefined ? 'undefined' : JSON.stringify(cron)}.

What it means

validateCron throws this when the cron argument is not a non-empty string (undefined, null, empty, or whitespace-only). It is the first gate before parsing the pattern with Croner, so callers get a clear message instead of an opaque parser failure.

Source

Thrown at packages/core/src/workflows/scheduler/cron.ts:11

import { Cron } from 'croner';

/**
 * Validate a cron expression. Throws if the pattern is invalid.
 *
 * @param cron - Cron expression (5-, 6-, or 7-part).
 * @param timezone - Optional IANA timezone (e.g. 'America/New_York').
 */
export function validateCron(cron: string, timezone?: string): void {
  if (typeof cron !== 'string' || cron.trim() === '') {
    throw new Error(
      `Invalid cron expression: expected a non-empty cron string (e.g. "0 * * * *"), but received ${cron === undefined ? 'undefined' : JSON.stringify(cron)}.`,
    );
  }
  // Croner throws synchronously on an invalid pattern when the job is
  // constructed. Validate the pattern on its own first so timezone problems
  // (which croner only surfaces lazily) are not mislabeled as cron errors.
  let job: Cron;
  try {
    job = new Cron(cron);
  } catch (error) {
    const reason = error instanceof Error ? error.message : String(error);
    throw new Error(`Invalid cron expression "${cron}": ${reason}`);
  }
  // The timezone is only exercised when a fire time is computed.
  if (timezone !== undefined) {
    try {
      new Cron(cron, { timezone }).nextRun();
    } catch (error) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Provide a valid non-empty cron string, e.g. '0 * * * *'.
  2. Check where the cron value is sourced (env var, config) and ensure it is set before calling.
  3. Add an upstream check that cron is a non-empty string before constructing a schedule.
  4. Validate config parsing so empty values are rejected at load time.

Example fix

// before
validateCron(config.schedule?.cron);
// after
if (!config.schedule?.cron) throw new Error('schedule.cron is required');
validateCron(config.schedule.cron, config.schedule.timezone);
Defensive patterns

Strategy: validation

Validate before calling

function assertCronPresent(cron: unknown): asserts cron is string {
  if (typeof cron !== 'string' || cron.trim() === '') throw new Error(`cron must be a non-empty string, got ${JSON.stringify(cron)}`);
}

Type guard

function isNonEmptyString(v: unknown): v is string { return typeof v === 'string' && v.trim() !== ''; }

Try / catch

try {
  validateCron(cron, tz);
} catch (e) {
  if ((e as Error).message.startsWith('Invalid cron expression: expected a non-empty')) {
    cron = DEFAULT_CRON; // or surface a config error
  } else throw e;
}

Prevention

When it happens

Trigger: Calling validateCron(undefined), validateCron(''), or validateCron(' '); passing a schedule config where the cron field was never populated (e.g. missing env var or empty YAML value).

Common situations: Schedule defined via config file/env where the cron key is missing; an object spread that omits cron; a form/UI submitting an empty cron field.

Related errors


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