mastra-ai/mastra · error
No active suspension to resume
Error message
No active suspension to resume
What it means
Thrown when attempting to resume a suspended tool execution but the session's suspension registry has no entry for the given toolCallId. Suspensions are tracked in `this.suspensions`; resume requires a matching active suspension so the library knows which tool, run, and resume boundary to restore. If the suspension was already resumed, cleared, or never registered, this error is thrown.
Source
Thrown at packages/core/src/agent-controller/session.ts:3857
* Interactive builtins (`ask_user`, `request_access`) are exempted from the
* approval re-check on resume: their resume schema is `z.string()` /
* `z.array(z.string())` which cannot carry the `{ approved }` field the
* approval gate demands, so re-entering the approval branch would always
* reject the answer. The caller already handled approval (setForTool policy,
* yolo mode, or a prior explicit approval gate).
*/
async resumeToolCall({
resumeData,
toolCallId,
requestContext: requestContextInput,
}: {
resumeData: any;
toolCallId: string;
requestContext?: RequestContext;
}): Promise<void> {
const suspension = this.suspensions.get({ toolCallId });
if (!suspension) {
throw new Error('No active suspension to resume');
}
const agent = this.machinery.getAgent();
// Remove before resuming so a re-suspend during the resumed run can
// re-register the same toolCallId without being clobbered by this cleanup.
// Drop the matching display-state entry too so the UI stops rendering the
// resolved prompt while any other parked suspensions stay visible.
this.suspensions.delete({ toolCallId });
this.displayState.deletePendingSuspension(toolCallId);
const requestContext = await this.machinery.buildRequestContext(requestContextInput);
const threadId = this.thread.getId();
if (!threadId) {
throw new Error('Cannot resume a suspended tool without a current thread');
}
await this.thread.ensureSubscription(threadId);View on GitHub (pinned to 75dd419e61)
Solutions
- Check for a pending suspension (via the session's suspension/pending-suspension state) before calling resume, and guard against duplicate resume calls.
- Verify the toolCallId matches the one supplied in the suspend event for the current session.
- If the process restarted, reload the suspended run state (e.g., by fetching the run/thread) to re-register suspensions before resuming.
- Ensure the resume call targets the same session instance that received the suspension.
Example fix
// before
await session.resumeSuspendedTool({ toolCallId, resumeData }); // may not exist
// after
const pending = session.getPendingSuspension?.(toolCallId);
if (pending) {
await session.resumeSuspendedTool({ toolCallId, resumeData });
} Defensive patterns
Strategy: validation
Validate before calling
// before resuming
const pending = session.getPendingSuspension?.(toolCallId);
if (!pending) {
console.warn('No pending suspension for', toolCallId);
return;
} Type guard
function hasPendingSuspension(session: { getPendingSuspension?: (id: string) => unknown }, toolCallId: string): boolean {
return Boolean(session.getPendingSuspension?.(toolCallId));
} Try / catch
try {
await session.resumeSuspendedTool({ toolCallId, resumeData });
} catch (err) {
if (err instanceof Error && err.message === 'No active suspension to resume') {
// already resumed or state lost; refresh suspension list from the run
} else throw err;
} Prevention
- Treat resume as one-shot: disable the control after the first call since the suspension is deleted on resume.
- Store the exact toolCallId from the suspend event, not a different identifier.
- After a process restart, reload run state to rebuild suspension tracking before resuming.
When it happens
Trigger: Calling the resume method with a toolCallId that has no active suspension — the suspension was already resumed (it is deleted before resuming), the run finished, the session restarted, or the ID is wrong/typo'd.
Common situations: Double-clicking 'Resume' so the second call finds the suspension already deleted; resuming after the process restarted and in-memory suspension state was lost; passing the wrong toolCallId (e.g., a run ID instead of a tool call ID); resuming a suspension registered in a different session instance.
Related errors
- Cannot resume a suspended tool without a current thread
- AGENT_RESUME_NO_SNAPSHOT_FOUND
- AGENT_RESUME_TOOL_CALL_NOT_SUSPENDED
- AGENT_SEND_STREAM_RESUME_NO_SUSPENDED_THREAD_RUN
- No active run to approve tool call for
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/fed739c2f5af670e.
Report an issue: GitHub.