mastra-ai/mastra · error · Error

Task not found: ${taskId}

Error message

Task not found: ${taskId}

What it means

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.

Source

Thrown at packages/core/src/background-tasks/manager.ts:339

      case 'fallback-sync':
        this.deregisterTaskContext(task.id);
        await storage.deleteTask(task.id);
        return { task, fallbackToSync: true };

      case 'queue':
      default:
        // Task stays pending in storage, will be dispatched when a slot opens
        return { task };
    }
  }

  async cancel(taskId: string): Promise<void> {
    if (this.initPromise) await this.initPromise;
    const storage = await this.getStorage();
    let task = await storage.getTask(taskId);
    if (!task) {
      throw new Error(`Task not found: ${taskId}`);
    }

    while (true) {
      if (
        task.status === 'completed' ||
        task.status === 'failed' ||
        task.status === 'cancelled' ||
        task.status === 'timed_out'
      ) {
        return; // no-op for terminal states
      }

      const previousStatus = task.status;
      const cancelled = await storage.updateTask(
        taskId,
        { status: 'cancelled', completedAt: new Date() },
        { expectedStatus: previousStatus },
      );

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the taskId came from an EnqueueResult/BackgroundTask.id on the same storage backend.
  2. Check the task exists before cancelling: `await storage.getTask(taskId)` or a manager list/get API.
  3. Treat cancel-of-unknown as a no-op in cleanup code: catch and ignore this error.
  4. Confirm all instances share the same storage configuration (same DB URL/collection).

Example fix

// before
await manager.cancel(taskId); // throws if unknown
// after
try {
  await manager.cancel(taskId);
} catch (e) {
  if (!String(e.message).startsWith('Task not found')) throw e;
  // already gone — nothing to cancel
}
Defensive patterns

Strategy: try-catch

Validate before calling

const task = await manager.getTask?.(taskId); // or storage.getTask(taskId)
if (!task) return; // nothing to cancel

Type guard

function isCancellable(task: BackgroundTask | undefined): boolean {
  return !!task && !['completed','failed','canceled'].includes(task.status);
}

Try / catch

try {
  await manager.cancel(taskId);
} catch (e) {
  if ((e as Error).message === `Task not found: ${taskId}`) return; // idempotent cancel
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/ebf29186ba239262. Report an issue: GitHub.