mastra-ai/mastra · error
Multiple suspended steps found: ${pathStrings.join(', ')}. P
Error message
Multiple suspended steps found: ${pathStrings.join(', ')}. Please specify which step to resume using the "step" parameter. What it means
Thrown when resume() is called without a step and the snapshot contains more than one suspended step path. The engine refuses to guess which one to continue and lists the paths (including nested paths) in the message.
Source
Thrown at packages/core/src/workflows/workflow.ts:4489
suspendedStepPaths.push([stepId, ...nestedPath]);
} else {
// For single-level suspension, just use the step ID
suspendedStepPaths.push([stepId]);
}
}
}
});
if (suspendedStepPaths.length === 0) {
throw new Error('No suspended steps found in this workflow run');
}
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.',
);
}
}
if (!params.retryCount) {
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(', ')}]`,
);
}
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Pass the step parameter naming which suspended step to resume: resume({ resumeData, step: 'stepId' }).
- For nested steps, pass the full dotted path or array path, e.g. step: ['parentStep', 'childStep'].
- Read the error message — it lists the available suspended paths — or inspect snapshot.suspendedPaths.
- Resume each suspended branch with separate resume() calls, one per step.
Example fix
// before
await run.resume({ resumeData });
// after
await run.resume({ resumeData, step: 'approvalBranchA' });
await run.resume({ resumeData, step: 'approvalBranchB' }); Defensive patterns
Strategy: validation
Validate before calling
const snapshot = await run.getWorkflowRunState();
const suspended = Object.keys(snapshot.suspendedPaths ?? {});
if (suspended.length > 1) {
throw new Error(`Must specify step; suspended: ${suspended.join(', ')}`);
} Type guard
function hasSingleSuspension(s: { suspendedPaths?: Record<string, unknown> }): boolean {
return Object.keys(s.suspendedPaths ?? {}).length === 1;
} Try / catch
try {
await run.resume({ resumeData });
} catch (e) {
if (e instanceof Error && e.message.startsWith('Multiple suspended steps found')) {
// parse listed paths or read suspendedPaths, then resume per-step
} else throw e;
} Prevention
- Design workflows so resume callers always know which step to continue.
- Pass step explicitly whenever the workflow has parallel suspend points.
- Resume each parallel branch individually.
- Keep step ids stable across deployments.
When it happens
Trigger: Calling resume({ resumeData }) with no step when the workflow suspended at two or more parallel/concurrent steps, or multiple steps suspended in a foreach; nested workflows suspended in several branches.
Common situations: Parallel branches each with a suspend() call; resuming a human-in-the-loop workflow with several approvals pending; developer added a second suspended step to an existing workflow whose clients still call resume() without step.
Related errors
- Cannot resume workflow: workflows store is required
- Cannot resume workflow: no snapshot found for runId ${this.r
- This workflow run was not suspended
- Resume label "${params.label}" not found. Available labels:
- No suspended steps found in this workflow run
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/f5b4baf656a15d49.
Report an issue: GitHub.