{"record":{"id":"f3b20d16a5516bdf","repo":"mastra-ai/mastra","slug":"concurrency-limit-reached-cannot-restart-task","errorCode":null,"errorMessage":"Concurrency limit reached, cannot restart task \"${taskId}\" — retry once a slot is available","messagePattern":"Concurrency limit reached, cannot restart task \"(.+?)\" — retry once a slot is available","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/core/src/background-tasks/manager.ts","lineNumber":493,"sourceCode":"    const task = await storage.getTask(taskId);\n    if (!task) {\n      throw new Error(`Task not found: ${taskId}`);\n    }\n    if (task.status !== 'running') {\n      throw new Error(`Cannot restart task in status '${task.status}' (expected 'running')`);\n    }\n\n    if (context) {\n      this.registerTaskContext(task.id, context);\n    }\n\n    const canRun = await this.checkConcurrency(task.agentId);\n    if (!canRun) {\n      // Restart sits outside the queue/fallback-sync paths — there's no\n      // synchronous caller to fall back to, and silently leaving the task\n      // running 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 restart task \"${taskId}\" — retry once a slot is available`);\n    }\n\n    await this.dispatch(task, true);\n\n    return task;\n  }\n\n  async getTask(taskId: string): Promise<BackgroundTask | null> {\n    const storage = await this.getStorage();\n    return storage.getTask(taskId);\n  }\n\n  async listTasks(filter: TaskFilter = {}): Promise<TaskListResult> {\n    const storage = await this.getStorage();\n    return storage.listTasks(filter);\n  }\n\n  /**","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/background-tasks/manager.ts#L475-L511","documentation":"Like resume, restart() bypasses the queue/dispatch fallback path, so before dispatching it checks the agent's concurrency limit. When no slot is available it throws rather than silently leaving the task running while doing nothing; the caller should retry once a slot frees.","triggerScenarios":"Calling manager.restart(taskId) when the task's agent already runs the maximum number of concurrent tasks allowed by its concurrency configuration.","commonSituations":"Bulk-restarting many running tasks during an incident response while the agent's concurrency budget is exhausted; deployments with low per-agent concurrency limits under heavy load.","solutions":["Catch the error and retry restart with exponential backoff.","Limit restart parallelism (e.g. process restarts in small batches with p-limit).","Increase the agent's concurrency limit if restart storms are routine."],"exampleFix":"// before\nawait Promise.all(ids.map(id => manager.restart(id))); // some throw on concurrency\n// after\nconst limit = pLimit(maxConcurrency);\nfor (const id of ids) {\n  limit(() => manager.restart(id)).catch(e => {\n    if (String(e).includes('Concurrency limit reached')) retryLater(id);\n  });\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async function restartWithBackoff(taskId, maxAttempts = 5) {\n  for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n    try {\n      return await manager.restart(taskId);\n    } catch (e) {\n      if (!e.message.includes('Concurrency limit reached') || attempt === maxAttempts) throw e;\n      await new Promise(r => setTimeout(r, 2 ** attempt * 1000));\n    }\n  }\n}","preventionTips":["Throttle bulk restarts to stay within the agent concurrency budget.","Monitor per-agent running-task counts and pause restart storms above threshold.","Prefer raising concurrency config over aggressive retry loops when restarts are routine."],"tags":["background-tasks","concurrency","rate-limiting"],"backgroundTag":"concurrency-limit-reached","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}