{"record":{"id":"7f94dac4cf2ee64d","repo":"mastra-ai/mastra","slug":"cannot-resume-task-in-status-task-status-exp","errorCode":null,"errorMessage":"Cannot resume task in status '${task.status}' (expected 'suspended')","messagePattern":"Cannot resume task in status '(.+?)' \\(expected 'suspended'\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/background-tasks/manager.ts","lineNumber":428,"sourceCode":"   * resumed run.\n   */\n  async resume(taskId: string, resumeData?: unknown): Promise<BackgroundTask> {\n    if (this.shuttingDown) {\n      throw new Error('BackgroundTaskManager is shutting down, cannot resume tasks');\n    }\n    if (!this.#mastra) {\n      throw new Error('Mastra is not registered with this manager');\n    }\n\n    if (this.initPromise) await this.initPromise;\n\n    const storage = await this.getStorage();\n    const task = await storage.getTask(taskId);\n    if (!task) {\n      throw new Error(`Task not found: ${taskId}`);\n    }\n    if (task.status !== 'suspended') {\n      throw new Error(`Cannot resume task in status '${task.status}' (expected 'suspended')`);\n    }\n\n    const canRun = await this.checkConcurrency(task.agentId);\n    if (!canRun) {\n      // Resume sits outside the queue/fallback-sync paths — there's no\n      // synchronous caller to fall back to, and silently leaving the task\n      // suspended hides the failure from the caller. Throw and let the\n      // caller retry once a slot frees.\n      throw new Error(`Concurrency limit reached, cannot resume task \"${taskId}\" — retry once a slot is available`);\n    }\n\n    // Resume publishes directly (not via dispatch()), so it needs its own\n    // lazy worker start for the library-mode process-restart case.\n    await this.#ensureExecutionWorkersStarted();\n\n    // Hand off to the worker subscriber. `task.resume` rides the same\n    // `TOPIC_DISPATCH` + `WORKER_GROUP` exactly-once channel as\n    // `task.dispatch`, so any worker (including a different process from","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/background-tasks/manager.ts#L410-L446","documentation":"BackgroundTaskManager.resume() only works on tasks currently in the 'suspended' state. The manager fetches the task record from storage and throws if its status is anything else (running, completed, failed, cancelled, etc.). This guard prevents resuming tasks that are not paused at a suspension point.","triggerScenarios":"Calling manager.resume(taskId) on a task whose stored status is not 'suspended' — e.g. the task already finished, failed, was cancelled, or is still actively running. Also happens when resuming the same task twice concurrently.","commonSituations":"Double-clicking a 'Resume' button in a UI so resume fires twice; retrying a resume call after a first resume already flipped the task to 'running'; attempting to resume a completed/failed task from a stale task list.","solutions":["Check the task's current status via storage/manager before calling resume and only resume tasks with status 'suspended'.","If resuming from a UI, disable the resume control after the first click and refresh the task state from the server.","If the task is completed/failed and you want it to run again, use restart() instead of resume()."],"exampleFix":"// before\nawait manager.resume(taskId); // throws if status isn't 'suspended'\n// after\nconst task = await manager.getTask(taskId);\nif (task?.status === 'suspended') {\n  await manager.resume(taskId);\n}","handlingStrategy":"validation","validationCode":"async function canResume(manager, taskId) {\n  const task = await manager.getTask(taskId);\n  return task?.status === 'suspended';\n}\n// call site:\nif (await canResume(manager, taskId)) await manager.resume(taskId);","typeGuard":"function isSuspended(task) {\n  return !!task && task.status === 'suspended';\n}","tryCatchPattern":"try {\n  await manager.resume(taskId);\n} catch (e) {\n  if (/Cannot resume task in status '(.+)'/.test(e.message)) {\n    const status = e.message.match(/Cannot resume task in status '(.+)'/)?.[1];\n    logger.warn(`Skipping resume: task is ${status}`);\n  } else throw e;\n}","preventionTips":["Always fetch fresh task status before resume — never act on cached state.","Guard UI resume actions against double invocation (disable after click).","Use restart()/start() for non-suspended tasks instead of forcing resume."],"tags":["background-tasks","state-machine","invalid-state"],"backgroundTag":"task-not-suspendable","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}