mastra-ai/mastra · error · Error
This workflow step "${steps?.[0]}" was not suspended. Availa
Error message
This workflow step "${steps?.[0]}" was not suspended. Available suspended steps: [${suspendedStepIds.join(', ')}] What it means
Mastra validates that the step named in resume's "step" parameter is actually in the snapshot's suspendedPaths before resuming. If the named step was not suspended (or already resumed/completed), it throws listing which steps ARE currently suspended so the caller can correct the request.
Source
Thrown at packages/core/src/workflows/evented/workflow.ts:2406
if (suspendedStepPaths.length === 1) {
// For single suspended step, use the full path
steps = suspendedStepPaths[0]!;
} else {
const pathStrings = suspendedStepPaths.map(path => `[${path.join(', ')}]`);
throw new Error(
`Multiple suspended steps found: ${pathStrings.join(', ')}. ` +
'Please specify which step to resume using the "step" parameter.',
);
}
}
// Validate that the step is actually suspended
const suspendedStepIds = Object.keys(snapshot?.suspendedPaths ?? {});
const isStepSuspended = suspendedStepIds.includes(steps?.[0] ?? '');
if (!isStepSuspended) {
throw new Error(
`This workflow step "${steps?.[0]}" was not suspended. Available suspended steps: [${suspendedStepIds.join(', ')}]`,
);
}
const resumePath = snapshot.suspendedPaths?.[steps[0]!] as any;
// Start with the snapshot's request context (old values)
const requestContextObj = snapshot.requestContext ?? {};
const requestContext = new RequestContext();
// First, set values from the snapshot
for (const [key, value] of Object.entries(requestContextObj)) {
requestContext.set(key, value);
}
// Then, override with any values from the passed request context (new values take precedence)
if (params.requestContext) {
for (const [key, value] of params.requestContext.entries()) {
requestContext.set(key, value);View on GitHub (pinned to 75dd419e61)
Solutions
- Use a step name/path exactly as listed in the error's "Available suspended steps" (nested steps use the path array, e.g. step: ['parallel', 'innerStep']).
- Check the run snapshot first: const snap = await workflow.getWorkflowRunState(runId); confirm Object.keys(snap.suspendedPaths).
- Guard against double-resume in application code (track resumed runs) since a step is no longer suspended after it resumes.
Example fix
// before
await workflow.resume({ runId, resumeData, step: 'approveStep' }); // typo
// after
await workflow.resume({ runId, resumeData, step: ['approval', 'approveStep'] }); Defensive patterns
Strategy: validation
Validate before calling
const snap = await workflow.getWorkflowRunState(runId);
const suspended = Object.keys(snap?.suspendedPaths ?? {});
if (!suspended.includes(stepId)) {
throw new Error(`${stepId} is not suspended; suspended: ${suspended.join(', ')}`);
}
await workflow.resume({ runId, resumeData, step: [stepId] }); Try / catch
try {
await workflow.resume({ runId, resumeData, step: [stepId] });
} catch (err) {
if (err instanceof Error && err.message.includes('was not suspended')) {
// refresh snapshot and resume whichever step is actually suspended
const snap = await workflow.getWorkflowRunState(runId);
const available = Object.keys(snap?.suspendedPaths ?? {});
if (available.length) await workflow.resume({ runId, resumeData, step: available as any });
} else throw err;
} Prevention
- Copy step IDs from the workflow definition rather than retyping them.
- Track which runs have already been resumed to avoid double-resume.
- For nested steps, always pass the full path array including parent step IDs.
When it happens
Trigger: workflow.resume({ runId, step: 'myStep' }) where myStep is not among Object.keys(snapshot.suspendedPaths) — the step never suspends, already resumed, or the name/step path is wrong (e.g. missing parent for nested steps).
Common situations: Typos in step IDs; resuming a step twice (second call fails); resuming after the workflow failed or finished; passing a top-level step name when the suspended step is nested inside a parallel/block (needs full path array).
Related errors
- Multiple suspended steps found: ${pathStrings.join(', ')}. P
- This workflow step "${steps?.[0]}" was not suspended. Availa
- Step is required and must be a valid step or array of steps
- ClaudeSDKAgent resumeData must include sessionId or continue
- CursorSDKAgent resumeData must include a message.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/6b7d3120b346081d.
Report an issue: GitHub.