mastra-ai/mastra · error
Snapshot not found for run ${this.runId}
Error message
Snapshot not found for run ${this.runId} What it means
Thrown by restart() when loadWorkflowSnapshot() returns no snapshot for the runId — the persisted state needed to re-drive the run cannot be found, so there is nothing to restart from.
Source
Thrown at packages/core/src/workflows/workflow.ts:4719
requestContext?: RequestContext<TRequestContext>;
outputWriter?: OutputWriter;
tracingOptions?: TracingOptions;
actor?: ActorSignal;
} & Partial<ObservabilityContext>): Promise<WorkflowResult<TState, TInput, TOutput, TSteps>> {
const observabilityContext = resolveObservabilityContext(rest);
const allowedEngines = ['default', 'evented'];
if (!allowedEngines.includes(this.workflowEngineType)) {
throw new Error(`restart() is not supported on ${this.workflowEngineType} workflows`);
}
const workflowsStore = await this.#mastra?.getStorage()?.getStore('workflows');
const snapshot = await workflowsStore?.loadWorkflowSnapshot({
workflowName: this.workflowId,
runId: this.runId,
});
if (!snapshot) {
throw new Error(`Snapshot not found for run ${this.runId}`);
}
// Parent parallel activeStepsPath can lag behind nested child completion after a crash:
// children may already be terminal while the parent still lists them as active and
// re-invokes restart(). Treat terminal snapshots as authoritative and reuse them.
// See https://github.com/mastra-ai/mastra/issues/20225
//
// Only statuses already represented on WorkflowResult are reconstructed here.
// Other terminal statuses (canceled/bailed) keep the existing createRestartExecutionParams
// "was not active" behavior — expanding WorkflowResult is out of scope for this fix.
if (snapshot.status === 'success' || snapshot.status === 'failed' || snapshot.status === 'tripwire') {
this.cleanup?.();
// Match fmtReturnValue: context keeps `input` alongside step results, and `input`
// is also surfaced as a top-level field on the returned WorkflowResult.
const hydratedSteps = hydrateSerializedStepErrors({ ...(snapshot.context ?? {}) }) ?? {};
// Strip internal bookkeeping (__state, metadata.nestedRunId) from step results so the
// reconstructed result matches what a live run would have returned via fmtReturnValue.
const steps = Object.fromEntries(View on GitHub (pinned to 75dd419e61)
Solutions
- Configure a persistent workflow storage (libsql/pg/upstash/redis) so snapshots survive crashes.
- Verify the recovery job reads runIds from the same storage instance the workflow wrote to.
- Skip runIds with no snapshot in your recovery loop (they never started or were pruned).
- Check for snapshot cleanup/TTL settings that might delete runs you still intend to restart.
Example fix
// before
await run.restart();
// after
const snapshot = await storage.loadWorkflowSnapshot({ workflowName: wf.id, runId });
if (snapshot) await run.restart();
else logger.warn(`Skipping ${runId}: no snapshot to restart from`); Defensive patterns
Strategy: validation
Validate before calling
const snapshot = await storage.loadWorkflowSnapshot({ workflowName: wf.id, runId });
if (!snapshot) {
logger.warn(`Skipping restart for ${runId}: no snapshot`);
return;
} Type guard
function canRestart(s: unknown): s is { status: string } {
return !!s && typeof s === 'object' && 'status' in s;
} Try / catch
try {
await run.restart();
} catch (e) {
if (e instanceof Error && e.message.startsWith('Snapshot not found for run')) {
// skip in recovery loop; run never persisted or was pruned
} else throw e;
} Prevention
- Use persistent storage if you rely on restart() for crash recovery.
- Only enqueue runIds for restart after their first snapshot is persisted.
- Align snapshot TTL/cleanup with recovery SLAs.
- Ensure recovery jobs read the same DB the workflows write to.
When it happens
Trigger: Calling restart() with a runId that has no snapshot: run never started, snapshot deleted, storage not shared across processes, or crash happened before the first snapshot was written.
Common situations: Recovery job replaying runIds after a redeploy that switched databases; in-memory storage lost on crash (which is exactly when restart is wanted — needs a persistent store); runIds from a different environment; snapshot pruning policies removing old runs.
Related errors
- No snapshot found for this workflow run: ${this.workflowId}
- DURABLE_AGENT_RECOVER_SNAPSHOT_NOT_FOUND
- Snapshot not found for runId ${runId}
- Snapshot context not found for runId ${snapshot?.runId}
- ATOMIC_STORAGE_OPERATIONS_NOT_SUPPORTED
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4a45fbbce1f1a7e4.
Report an issue: GitHub.