mastra-ai/mastra · error · Error

Stored sleep "${entry.id}" missing literal duration.

Error message

Stored sleep "${entry.id}" missing literal duration.

What it means

When rehydrating a stored workflow, a `sleep` entry must carry a literal numeric duration (durations can't be recomputed from runtime state). If entry.duration is not a number, applyGraphEntry throws this error naming the stored step id.

Source

Thrown at packages/core/src/workflows/dynamic/rehydrate.ts:100

  wf: any,
  entry: ValidatableStepFlowEntry,
  mastra: Mastra,
  schemaOpts?: JsonSchemaToZodOptions,
): void {
  switch (entry.type) {
    case 'agent':
    case 'tool':
      wf.__pushStepFlowEntry(rehydrateSingleEntry(entry, mastra, schemaOpts), entry);
      return;
    case 'mapping': {
      const cfg = parseMapConfig(entry.mapConfig, entry.id);
      const live = rehydrateMapConfig(cfg, mastra);
      wf.map(live, { id: entry.id });
      return;
    }
    case 'sleep': {
      if (typeof entry.duration !== 'number') {
        throw new Error(`Stored sleep "${entry.id}" missing literal duration.`);
      }
      // Push directly (not wf.sleep()) so the stored step id survives the
      // round-trip — the builder generates a fresh random id per call.
      const live: StepFlowEntry = { type: 'sleep', id: entry.id, duration: entry.duration };
      wf.__pushStepFlowEntry(live, live);
      return;
    }
    case 'sleepUntil': {
      if (!(entry.date instanceof Date) && typeof entry.date !== 'string') {
        throw new Error(`Stored sleepUntil "${entry.id}" missing literal date.`);
      }
      const date = entry.date instanceof Date ? entry.date : new Date(entry.date);
      if (Number.isNaN(date.getTime())) {
        throw new Error(`Stored sleepUntil "${entry.id}" has an unparseable date: ${String(entry.date)}`);
      }
      const live: StepFlowEntry = { type: 'sleepUntil', id: entry.id, date };
      wf.__pushStepFlowEntry(live, { type: 'sleepUntil', id: entry.id, date });
      return;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Fix the stored entry so duration is a literal number of milliseconds.
  2. Re-save the workflow step through the builder API with a numeric duration.
  3. Convert string/object durations to milliseconds when migrating stored definitions.

Example fix

// before
{ type: 'sleep', id: 'wait', duration: '30s' }
// after
{ type: 'sleep', id: 'wait', duration: 30000 }
Defensive patterns

Strategy: validation

Validate before calling

function assertSleepEntry(entry) {
  if (entry.type === 'sleep' && typeof entry.duration !== 'number') {
    throw new TypeError(`Sleep step "${entry.id}" must have a numeric duration`);
  }
}

Type guard

function isValidSleepEntry(e: { type: string; duration?: unknown }): e is { type: 'sleep'; id: string; duration: number } {
  return e.type === 'sleep' && typeof e.duration === 'number';
}

Try / catch

try {
  const wf = await rehydrateWorkflow(stored, mastra);
} catch (e) {
  if (e instanceof Error && e.message.includes('missing literal duration')) {
    // fix the stored sleep entry with a numeric duration and retry
  }
  throw e;
}

Prevention

When it happens

Trigger: A stored workflow graph contains `{ type: 'sleep', id, duration: undefined/null/'30s' }` — e.g. the sleep was created from a dynamic value that was never serialized, the stored row is corrupted, or a hand-written definition used a non-numeric duration.

Common situations: Sleeps configured via a builder UI with a string like '30' or '30s' instead of a number; storage dropping the field; definitions hand-migrated from another format where duration was an object ({seconds: 30}).

Related errors


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