{"record":{"id":"fed739c2f5af670e","repo":"mastra-ai/mastra","slug":"no-active-suspension-to-resume","errorCode":null,"errorMessage":"No active suspension to resume","messagePattern":"No active suspension to resume","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agent-controller/session.ts","lineNumber":3857,"sourceCode":"   * Interactive builtins (`ask_user`, `request_access`) are exempted from the\n   * approval re-check on resume: their resume schema is `z.string()` /\n   * `z.array(z.string())` which cannot carry the `{ approved }` field the\n   * approval gate demands, so re-entering the approval branch would always\n   * reject the answer. The caller already handled approval (setForTool policy,\n   * yolo mode, or a prior explicit approval gate).\n   */\n  async resumeToolCall({\n    resumeData,\n    toolCallId,\n    requestContext: requestContextInput,\n  }: {\n    resumeData: any;\n    toolCallId: string;\n    requestContext?: RequestContext;\n  }): Promise<void> {\n    const suspension = this.suspensions.get({ toolCallId });\n    if (!suspension) {\n      throw new Error('No active suspension to resume');\n    }\n\n    const agent = this.machinery.getAgent();\n\n    // Remove before resuming so a re-suspend during the resumed run can\n    // re-register the same toolCallId without being clobbered by this cleanup.\n    // Drop the matching display-state entry too so the UI stops rendering the\n    // resolved prompt while any other parked suspensions stay visible.\n    this.suspensions.delete({ toolCallId });\n    this.displayState.deletePendingSuspension(toolCallId);\n\n    const requestContext = await this.machinery.buildRequestContext(requestContextInput);\n    const threadId = this.thread.getId();\n    if (!threadId) {\n      throw new Error('Cannot resume a suspended tool without a current thread');\n    }\n\n    await this.thread.ensureSubscription(threadId);","sourceCodeStart":3839,"sourceCodeEnd":3875,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent-controller/session.ts#L3839-L3875","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait session.resumeSuspendedTool({ toolCallId, resumeData }); // may not exist\n\n// after\nconst pending = session.getPendingSuspension?.(toolCallId);\nif (pending) {\n  await session.resumeSuspendedTool({ toolCallId, resumeData });\n}","handlingStrategy":"validation","validationCode":"// before resuming\nconst pending = session.getPendingSuspension?.(toolCallId);\nif (!pending) {\n  console.warn('No pending suspension for', toolCallId);\n  return;\n}","typeGuard":"function hasPendingSuspension(session: { getPendingSuspension?: (id: string) => unknown }, toolCallId: string): boolean {\n  return Boolean(session.getPendingSuspension?.(toolCallId));\n}","tryCatchPattern":"try {\n  await session.resumeSuspendedTool({ toolCallId, resumeData });\n} catch (err) {\n  if (err instanceof Error && err.message === 'No active suspension to resume') {\n    // already resumed or state lost; refresh suspension list from the run\n  } else throw err;\n}","preventionTips":["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."],"tags":["agent","suspension","resume","lifecycle"],"backgroundTag":"no-active-suspension","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}