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
- 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).
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
- 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.
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
- Background task not found
- Model "${modelId}" is not available. Available models: ${ids
- ACP connection is not initialized
- Model "${this.options.model}" is not available. Available mo
- ClaudeSDKAgent resumeData must include either sessionId or c
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/ebf29186ba239262.
Report an issue: GitHub.