mastra-ai/mastra · error · Error

This workflow run was not suspended

Error message

This workflow run was not suspended

What it means

resume() only makes sense for runs parked at a suspend point. The snapshot was found in storage but its status is not 'suspended' (e.g. 'running', 'success', 'failed'), so resuming would be meaningless and the library throws.

Source

Thrown at packages/core/src/workflows/evented/workflow.ts:2336

          workflowId: this.workflowId,
          runId: this.runId,
          resourceId: this.resourceId,
        },
      });
    }

    const workflowsStore = await this.mastra?.getStorage()?.getStore('workflows');
    if (!workflowsStore) {
      throw new Error('Cannot resume workflow: workflows store is required');
    }
    const snapshot = await waitForSuspendedSnapshot(workflowsStore, this.workflowId, this.runId);
    if (!snapshot) {
      throw new Error(`Cannot resume workflow: no snapshot found for runId ${this.runId}`);
    }

    // Check if workflow is suspended before proceeding
    if (snapshot.status !== 'suspended') {
      throw new Error('This workflow run was not suspended');
    }

    // Resolve label to step path if provided
    const snapshotResumeLabel = params.label ? snapshot?.resumeLabels?.[params.label] : undefined;

    // Validate label exists if provided
    if (params.label && !snapshotResumeLabel) {
      const availableLabels = Object.keys(snapshot?.resumeLabels ?? {});
      throw new Error(
        `Resume label "${params.label}" not found. ` + `Available labels: [${availableLabels.join(', ')}]`,
      );
    }

    // Label takes precedence over step param
    const stepParam = snapshotResumeLabel?.stepId ?? params.step;

    // Auto-detect suspended steps if no step is provided
    let steps: string[];

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check the run status before resuming and skip if not 'suspended'
  2. Deduplicate resume calls (idempotency key or in-flight guard)
  3. Fetch the run's latest snapshot to see the actual status and outcome (success/error) instead of resuming

Example fix

// before
await workflow.resume({ runId, step, resumeData });
// after
const snapshot = await storage.loadWorkflowSnapshot({ workflowId, runId });
if (snapshot?.status === 'suspended') {
  await workflow.resume({ runId, step, resumeData });
}
Defensive patterns

Strategy: validation

Validate before calling

const snapshot = await storage.loadWorkflowSnapshot({ workflowId, runId });
if (snapshot?.status !== 'suspended') {
  throw new Error(`Run is ${snapshot?.status}; only suspended runs can be resumed`);
}

Type guard

function isSuspended(s) {
  return !!s && s.status === 'suspended';
}

Try / catch

try {
  await run.resume({ runId, step, resumeData });
} catch (e) {
  if (e.message === 'This workflow run was not suspended') {
    // treat as idempotent no-op or fetch final result
    return getRunResult(runId);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling resume() on a run whose persisted snapshot.status !== 'suspended' — the run already completed, already failed, is still actively running, or was resumed previously.

Common situations: Double-resume from a retry queue or duplicate event handler; user clicking 'resume' twice in a UI; resuming after the workflow already finished because a watch loop didn't observe completion; stale UI state showing an old suspended run.

Related errors


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