mastra-ai/mastra · error · Error
Task has not been dispatched yet
Error message
Task has not been dispatched yet
What it means
Thrown by the synchronous `task` getter of a BackgroundTaskHandle when the handle has not been dispatched. The handle stores the task ID in a closure variable that is only set inside `dispatch()`; reading `handle.task` before dispatching means no ID exists yet, so the getter throws instead of returning a bogus task object.
Source
Thrown at packages/core/src/background-tasks/create.ts:44
* onResult: (params) => messageList.addToolResult(params),
* },
* });
*
* const { task, fallbackToSync } = await bgTask.dispatch();
* const completed = await bgTask.waitForCompletion();
* await bgTask.cancel();
* ```
*/
export function createBackgroundTask(
manager: BackgroundTaskManager,
options: CreateBackgroundTaskOptions,
): BackgroundTaskHandle {
const { context, ...payload } = options;
let taskId: string | undefined;
return {
get task() {
if (!taskId) throw new Error('Task has not been dispatched yet');
// Synchronous access to task ID — full task data requires async getTask()
return { id: taskId } as any;
},
async dispatch() {
const result = await manager.enqueue(payload, context);
taskId = result.task.id;
return result;
},
async checkIfSuspended(args: CheckIfSuspendedPayload) {
const result = await manager.listTasks({
toolCallId: args.toolCallId,
runId: args.runId,
agentId: args.agentId,
threadId: args.threadId,
resourceId: args.resourceId,
toolName: args.toolName,View on GitHub (pinned to 75dd419e61)
Solutions
- Call `await handle.dispatch()` before reading `handle.task`.
- If you need the ID without dispatching, restructure to dispatch first and then use the returned ID.
- Track the dispatched ID yourself from `dispatch()`'s result and pass it where needed instead of reading the sync getter.
Example fix
// before const handle = createBackgroundTask(options); console.log(handle.task.id); // throws // after const handle = createBackgroundTask(options); await handle.dispatch(); console.log(handle.task.id);
Defensive patterns
Strategy: try-catch
Validate before calling
// before reading the sync getter let dispatched = false; const handle = createBackgroundTask(options); await handle.dispatch(); dispatched = true; if (dispatched) console.log(handle.task.id);
Type guard
function isDispatched(handle: { task?: { id: string } }): boolean {
try {
return typeof handle.task?.id === 'string';
} catch {
return false;
}
} Try / catch
let taskId: string | undefined;
try {
taskId = handle.task.id;
} catch (err) {
if (err instanceof Error && err.message === 'Task has not been dispatched yet') {
await handle.dispatch();
taskId = handle.task.id;
} else throw err;
} Prevention
- Always await dispatch() immediately after creating a background task handle.
- Never read handle.task in render paths that run before dispatch resolves.
- Keep the ID from dispatch()'s result as your source of truth.
When it happens
Trigger: Accessing `handle.task` (or `.task.id`) on a handle returned by the background-task create function before calling `await handle.dispatch()`.
Common situations: Reading the task ID immediately after creating the handle and forgetting to dispatch; using the getter in a render/log statement before the dispatch promise resolves; assuming `create` itself enqueues the task when it only builds the handle.
Related errors
- BackgroundTaskManager is shutting down, cannot initialize
- BackgroundTaskManager is shutting down, cannot restart tasks
- MastraAuthBetterAuth is not initialized — init() must run fi
- Shared browser not launched. Call createSharedSession() firs
- Browser not launched
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/8383d37a36aa8d73.
Report an issue: GitHub.