mastra-ai/mastra · error · Error

${errorInfo.message}

Error message

${errorInfo.message}

What it means

Inside the generated background-task workflow, when the wrapped task body throws, the workflow records the failure, runs 'failed' completion hooks, publishes a task.failed lifecycle event, deregisters the task context, and re-throws the original error message. This is the propagation of the underlying task's failure, not a manager bug.

Source

Thrown at packages/core/src/background-tasks/workflow.ts:97

      const executor =
        ctx?.executor ??
        (task.agentId ? manager.getStaticExecutor(`${task.agentId}:${task.toolName}`) : undefined) ??
        manager.getStaticExecutor(task.toolName);
      if (!executor) {
        const errorInfo = {
          message:
            `No executor registered for tool "${task.toolName}". ` +
            `Register the tool on Mastra (so workers can resolve it cross-process) ` +
            `or run the task in the same process as the producer.`,
        };
        await storage.updateTask(taskId, { status: 'failed', error: errorInfo, completedAt: new Date() });
        const failedTask = await storage.getTask(taskId);
        if (failedTask) {
          await manager.runLocalCompletionHooks(failedTask, 'failed', { error: errorInfo });
          await manager.publishLifecycleEvent('task.failed', failedTask);
        }
        manager.deregisterTaskContext(taskId);
        throw new Error(errorInfo.message);
      }

      // Throttled progress publisher.
      const progressThrottleMs = manager.config.progressThrottleMs;
      const shouldThrottleProgress =
        typeof progressThrottleMs === 'number' && Number.isFinite(progressThrottleMs) && progressThrottleMs > 0;
      let lastProgressEmitMs: number | undefined;
      const onProgress = async (chunk: any) => {
        if (shouldThrottleProgress) {
          const now = Date.now();
          if (lastProgressEmitMs !== undefined && now - lastProgressEmitMs < progressThrottleMs) return;
          lastProgressEmitMs = now;
        }
        await manager.publishLifecycleEvent('task.output', { ...task, chunk });
      };

      const abortController = new AbortController();
      if (!manager.registerActiveAbortController(taskId, abortController)) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Inspect the errorInfo.message (and the task record's failure details in storage) to find the root cause thrown by your task body.
  2. Add try/catch inside the task body for recoverable failures and return a structured result instead of throwing.
  3. Subscribe to the task.failed lifecycle event / completion hooks to log full error details.
  4. Fix the underlying fault (invalid input, missing credentials, upstream API outage) indicated by the message.

Example fix

// before
await manager.workflow(async ({ data }) => {
  return await callModel(data.prompt); // rejects -> task.failed -> rethrown
});
// after
await manager.workflow(async ({ data }) => {
  try {
    return await callModel(data.prompt);
  } catch (err) {
    logger.error('task body failed', err);
    throw new Error(`Model call failed: ${err.message}`); // clearer root cause
  }
});
Defensive patterns

Strategy: try-catch

Validate before calling

function validateTaskInput(input, schema) {
  const result = schema.safeParse(input);
  if (!result.success) throw new Error(`Invalid task input: ${result.error.message}`);
  return result.data;
}
// validate BEFORE starting the workflow so failures don't surface mid-run

Try / catch

try {
  await manager.workflow(taskBody, { /* ... */ });
} catch (e) {
  logger.error('Background task failed', { message: e.message, taskId });
  // inspect the failed task record + runLocalCompletionHooks data for root cause
  await alerting.notifyTaskFailure(taskId, e.message);
}

Prevention

When it happens

Trigger: Any uncaught exception thrown inside the function wrapped by manager.workflow()/buildBackgroundTaskWorkflow — the errorInfo comes from the failed task body, e.g. an LLM call failure, validation error, or unhandled rejection in the task handler.

Common situations: A task's model API call fails (rate limit, auth), the task body dereferences undefined data, or an awaited sub-operation rejects — surfacing via the workflow run as this re-thrown error.

Related errors


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