mastra-ai/mastra · warning · Error
Concurrency limit reached, cannot resume task "${taskId}" —
Error message
Concurrency limit reached, cannot resume task "${taskId}" — retry once a slot is available What it means
Before resuming a task, resume() checks the per-agent concurrency limit via checkConcurrency(). Unlike the normal dispatch path there is no queue or synchronous fallback for resume, so when all slots are busy the manager throws instead of silently leaving the task suspended. The caller is expected to retry once a slot frees.
Source
Thrown at packages/core/src/background-tasks/manager.ts:437
if (this.initPromise) await this.initPromise;
const storage = await this.getStorage();
const task = await storage.getTask(taskId);
if (!task) {
throw new Error(`Task not found: ${taskId}`);
}
if (task.status !== 'suspended') {
throw new Error(`Cannot resume task in status '${task.status}' (expected 'suspended')`);
}
const canRun = await this.checkConcurrency(task.agentId);
if (!canRun) {
// Resume sits outside the queue/fallback-sync paths — there's no
// synchronous caller to fall back to, and silently leaving the task
// suspended hides the failure from the caller. Throw and let the
// caller retry once a slot frees.
throw new Error(`Concurrency limit reached, cannot resume task "${taskId}" — retry once a slot is available`);
}
// Resume publishes directly (not via dispatch()), so it needs its own
// lazy worker start for the library-mode process-restart case.
await this.#ensureExecutionWorkersStarted();
// Hand off to the worker subscriber. `task.resume` rides the same
// `TOPIC_DISPATCH` + `WORKER_GROUP` exactly-once channel as
// `task.dispatch`, so any worker (including a different process from
// the one that suspended the task) can pick it up.
await this.pubsub.publish(TOPIC_DISPATCH, {
type: 'task.resume',
data: { taskId, resumeData },
runId: taskId,
});
return task;
}View on GitHub (pinned to 75dd419e61)
Solutions
- Catch the error and retry resume with backoff until a concurrency slot frees.
- Serialize resumes (small concurrency, e.g. p-limit) so you never exceed the agent's limit.
- Raise the agent's max concurrency configuration if the limit is routinely the bottleneck.
Example fix
// before
await manager.resume(taskId); // throws when slots are full
// after
async function resumeWithRetry(taskId: string, retries = 5) {
for (let i = 0; i < retries; i++) {
try { return await manager.resume(taskId); }
catch (e) {
if (!String(e).includes('Concurrency limit reached')) throw e;
await new Promise(r => setTimeout(r, 2 ** i * 1000));
}
}
throw new Error(`Could not resume ${taskId}: concurrency slots never freed`);
} Defensive patterns
Strategy: retry
Try / catch
async function resumeWithBackoff(taskId, maxAttempts = 5) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await manager.resume(taskId);
} catch (e) {
if (!String(e.message).includes('Concurrency limit reached') || attempt === maxAttempts) throw e;
await new Promise(r => setTimeout(r, 2 ** attempt * 500 + Math.random() * 250));
}
}
} Prevention
- Cap parallel resume/restart calls to the agent's concurrency limit using a semaphore or p-limit.
- Add jittered exponential backoff for any resume issued in bulk.
- Track in-flight tasks per agent client-side before issuing resumes.
When it happens
Trigger: Calling manager.resume(taskId) when the task's agent already has the maximum configured number of concurrently running tasks (agent concurrency limit reached).
Common situations: Resuming many suspended tasks in a loop after a process restart while all concurrency slots are still occupied; high-traffic deployments with tight per-agent concurrency settings.
Related errors
- Concurrency limit reached, cannot restart task "${taskId}" —
- Concurrency limit reached, cannot enqueue task for tool "${t
- MastraFactory.prepare() called twice
- Factory kickoff lease was lost before completion.
- ${file} is in use by another process — is another Mastra Cod
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/ba9dec2831f5b350.
Report an issue: GitHub.