{"record":{"id":"ebf29186ba239262","repo":"mastra-ai/mastra","slug":"task-not-found-taskid","errorCode":null,"errorMessage":"Task not found: ${taskId}","messagePattern":"Task not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/background-tasks/manager.ts","lineNumber":339,"sourceCode":"\n      case 'fallback-sync':\n        this.deregisterTaskContext(task.id);\n        await storage.deleteTask(task.id);\n        return { task, fallbackToSync: true };\n\n      case 'queue':\n      default:\n        // Task stays pending in storage, will be dispatched when a slot opens\n        return { task };\n    }\n  }\n\n  async cancel(taskId: string): Promise<void> {\n    if (this.initPromise) await this.initPromise;\n    const storage = await this.getStorage();\n    let task = await storage.getTask(taskId);\n    if (!task) {\n      throw new Error(`Task not found: ${taskId}`);\n    }\n\n    while (true) {\n      if (\n        task.status === 'completed' ||\n        task.status === 'failed' ||\n        task.status === 'cancelled' ||\n        task.status === 'timed_out'\n      ) {\n        return; // no-op for terminal states\n      }\n\n      const previousStatus = task.status;\n      const cancelled = await storage.updateTask(\n        taskId,\n        { status: 'cancelled', completedAt: new Date() },\n        { expectedStatus: previousStatus },\n      );","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/background-tasks/manager.ts#L321-L357","documentation":"cancel(taskId) looks up the task record in the backgroundTasks store and throws if no record exists for that ID. Cancellation requires the persisted task row (to locate and abort the underlying workflow run), so an unknown ID is a hard error.","triggerScenarios":"Cancelling a taskId that was never enqueued; a typo'd or stale ID; the task row was deleted (retention/cleanup or the earlier concurrency-reject delete); cancelling on a different deployment/storage instance than where the task was created.","commonSituations":"Retrying cancel after retention purged old tasks; multi-instance setups where instance A cancels a task stored only in instance B's DB; app-level maps caching task IDs past their storage lifetime.","solutions":["Verify the taskId came from an EnqueueResult/BackgroundTask.id on the same storage backend.","Check the task exists before cancelling: `await storage.getTask(taskId)` or a manager list/get API.","Treat cancel-of-unknown as a no-op in cleanup code: catch and ignore this error.","Confirm all instances share the same storage configuration (same DB URL/collection)."],"exampleFix":"// before\nawait manager.cancel(taskId); // throws if unknown\n// after\ntry {\n  await manager.cancel(taskId);\n} catch (e) {\n  if (!String(e.message).startsWith('Task not found')) throw e;\n  // already gone — nothing to cancel\n}","handlingStrategy":"try-catch","validationCode":"const task = await manager.getTask?.(taskId); // or storage.getTask(taskId)\nif (!task) return; // nothing to cancel","typeGuard":"function isCancellable(task: BackgroundTask | undefined): boolean {\n  return !!task && !['completed','failed','canceled'].includes(task.status);\n}","tryCatchPattern":"try {\n  await manager.cancel(taskId);\n} catch (e) {\n  if ((e as Error).message === `Task not found: ${taskId}`) return; // idempotent cancel\n  throw e;\n}","preventionTips":["Only cancel IDs obtained from EnqueueResult on the same storage backend.","Make cancel idempotent by swallowing not-found errors in cleanup paths.","Verify all instances point at the same storage DB.","Don't cache task IDs beyond storage retention."],"tags":["background-tasks","not-found","cancel"],"backgroundTag":"task-not-found","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}