mastra-ai/mastra · warning · Error

Concurrency limit reached, cannot restart task "${taskId}" —

Error message

Concurrency limit reached, cannot restart task "${taskId}" — retry once a slot is available

What it means

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.

Source

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

    const task = await storage.getTask(taskId);
    if (!task) {
      throw new Error(`Task not found: ${taskId}`);
    }
    if (task.status !== 'running') {
      throw new Error(`Cannot restart task in status '${task.status}' (expected 'running')`);
    }

    if (context) {
      this.registerTaskContext(task.id, context);
    }

    const canRun = await this.checkConcurrency(task.agentId);
    if (!canRun) {
      // Restart sits outside the queue/fallback-sync paths — there's no
      // synchronous caller to fall back to, and silently leaving the task
      // running hides the failure from the caller. Throw and let the
      // caller retry once a slot frees.
      throw new Error(`Concurrency limit reached, cannot restart task "${taskId}" — retry once a slot is available`);
    }

    await this.dispatch(task, true);

    return task;
  }

  async getTask(taskId: string): Promise<BackgroundTask | null> {
    const storage = await this.getStorage();
    return storage.getTask(taskId);
  }

  async listTasks(filter: TaskFilter = {}): Promise<TaskListResult> {
    const storage = await this.getStorage();
    return storage.listTasks(filter);
  }

  /**

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Catch the error and retry restart with exponential backoff.
  2. Limit restart parallelism (e.g. process restarts in small batches with p-limit).
  3. Increase the agent's concurrency limit if restart storms are routine.

Example fix

// before
await Promise.all(ids.map(id => manager.restart(id))); // some throw on concurrency
// after
const limit = pLimit(maxConcurrency);
for (const id of ids) {
  limit(() => manager.restart(id)).catch(e => {
    if (String(e).includes('Concurrency limit reached')) retryLater(id);
  });
}
Defensive patterns

Strategy: retry

Try / catch

async function restartWithBackoff(taskId, maxAttempts = 5) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await manager.restart(taskId);
    } catch (e) {
      if (!e.message.includes('Concurrency limit reached') || attempt === maxAttempts) throw e;
      await new Promise(r => setTimeout(r, 2 ** attempt * 1000));
    }
  }
}

Prevention

When it happens

Trigger: Calling manager.restart(taskId) when the task's agent already runs the maximum number of concurrent tasks allowed by its concurrency configuration.

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

Related errors


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