mastra-ai/mastra · error · Error
BackgroundTaskManager is shutting down, cannot resume tasks
Error message
BackgroundTaskManager is shutting down, cannot resume tasks
What it means
resume(taskId, resumeData) refuses to resume suspended tasks once shutdown has started. Resuming re-dispatches a workflow run and needs live workers/pubsub, which are unavailable during teardown. The library throws instead of resuming into a dying process.
Source
Thrown at packages/core/src/background-tasks/manager.ts:414
runId: taskId,
});
}
return;
}
}
/**
* Resume a suspended task. The tool executor must be re-registered via
* `registerTaskContext(taskId, ...)` before calling this if the original
* registration is gone (e.g. process restart) — the manager doesn't
* rehydrate executor closures from storage.
*
* `resumeData` is forwarded to the tool's `execute` options on the
* resumed run.
*/
async resume(taskId: string, resumeData?: unknown): Promise<BackgroundTask> {
if (this.shuttingDown) {
throw new Error('BackgroundTaskManager is shutting down, cannot resume tasks');
}
if (!this.#mastra) {
throw new Error('Mastra is not registered with this manager');
}
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) {View on GitHub (pinned to 75dd419e61)
Solutions
- Defer resume until after restart: check manager.shuttingDown and persist resumeData for post-restart replay.
- Perform shutdown drain first: resume/complete suspended tasks, then call shutdown().
- Re-create the manager (new process/instance) and resume there once shuttingDown is false.
- Gate auto-resume handlers on the shutdown flag.
Example fix
// before
await manager.resume(taskId, data); // may throw during shutdown
// after
if (manager.shuttingDown) {
await saveForRestart(taskId, data); // replay after restart
} else {
await manager.resume(taskId, data);
} Defensive patterns
Strategy: validation
Validate before calling
if (manager.shuttingDown) {
await saveForRestart(taskId, resumeData);
return;
} Try / catch
try {
await manager.resume(taskId, data);
} catch (e) {
if ((e as Error).message.includes('shutting down, cannot resume')) {
await persistResumeIntent(taskId, data); // replay after restart
return;
}
throw e;
} Prevention
- Drain suspended tasks before calling shutdown().
- Check shuttingDown before auto-resume paths fire.
- Persist resume intents for post-restart replay.
- Avoid retry loops against a shutting-down manager.
When it happens
Trigger: Calling manager.resume() during SIGTERM/shutdown handling; an auto-resume path (handleResume) firing while shutdown() runs; resuming background tasks from a request handler processed during drain.
Common situations: Deploy-time drain with pending suspended tasks; retry loops that keep calling resume while shutdown is in progress; tests tearing down managers while resume is still pending.
Related errors
- BackgroundTaskManager is shutting down, cannot initialize
- BackgroundTaskManager is shutting down, cannot enqueue new t
- BackgroundTaskManager is shutting down, cannot restart tasks
- ClaudeSDKAgent resumeData must include sessionId or continue
- CursorSDKAgent resumeData must include a message.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/9714e0e926be00c6.
Report an issue: GitHub.