{"record":{"id":"34f8970fbfbf4731","repo":"mastra-ai/mastra","slug":"errorinfo-message","errorCode":null,"errorMessage":"${errorInfo.message}","messagePattern":"\\$\\{errorInfo\\.message\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/background-tasks/workflow.ts","lineNumber":97,"sourceCode":"      const executor =\n        ctx?.executor ??\n        (task.agentId ? manager.getStaticExecutor(`${task.agentId}:${task.toolName}`) : undefined) ??\n        manager.getStaticExecutor(task.toolName);\n      if (!executor) {\n        const errorInfo = {\n          message:\n            `No executor registered for tool \"${task.toolName}\". ` +\n            `Register the tool on Mastra (so workers can resolve it cross-process) ` +\n            `or run the task in the same process as the producer.`,\n        };\n        await storage.updateTask(taskId, { status: 'failed', error: errorInfo, completedAt: new Date() });\n        const failedTask = await storage.getTask(taskId);\n        if (failedTask) {\n          await manager.runLocalCompletionHooks(failedTask, 'failed', { error: errorInfo });\n          await manager.publishLifecycleEvent('task.failed', failedTask);\n        }\n        manager.deregisterTaskContext(taskId);\n        throw new Error(errorInfo.message);\n      }\n\n      // Throttled progress publisher.\n      const progressThrottleMs = manager.config.progressThrottleMs;\n      const shouldThrottleProgress =\n        typeof progressThrottleMs === 'number' && Number.isFinite(progressThrottleMs) && progressThrottleMs > 0;\n      let lastProgressEmitMs: number | undefined;\n      const onProgress = async (chunk: any) => {\n        if (shouldThrottleProgress) {\n          const now = Date.now();\n          if (lastProgressEmitMs !== undefined && now - lastProgressEmitMs < progressThrottleMs) return;\n          lastProgressEmitMs = now;\n        }\n        await manager.publishLifecycleEvent('task.output', { ...task, chunk });\n      };\n\n      const abortController = new AbortController();\n      if (!manager.registerActiveAbortController(taskId, abortController)) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/background-tasks/workflow.ts#L79-L115","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the errorInfo.message (and the task record's failure details in storage) to find the root cause thrown by your task body.","Add try/catch inside the task body for recoverable failures and return a structured result instead of throwing.","Subscribe to the task.failed lifecycle event / completion hooks to log full error details.","Fix the underlying fault (invalid input, missing credentials, upstream API outage) indicated by the message."],"exampleFix":"// before\nawait manager.workflow(async ({ data }) => {\n  return await callModel(data.prompt); // rejects -> task.failed -> rethrown\n});\n// after\nawait manager.workflow(async ({ data }) => {\n  try {\n    return await callModel(data.prompt);\n  } catch (err) {\n    logger.error('task body failed', err);\n    throw new Error(`Model call failed: ${err.message}`); // clearer root cause\n  }\n});","handlingStrategy":"try-catch","validationCode":"function validateTaskInput(input, schema) {\n  const result = schema.safeParse(input);\n  if (!result.success) throw new Error(`Invalid task input: ${result.error.message}`);\n  return result.data;\n}\n// validate BEFORE starting the workflow so failures don't surface mid-run","typeGuard":null,"tryCatchPattern":"try {\n  await manager.workflow(taskBody, { /* ... */ });\n} catch (e) {\n  logger.error('Background task failed', { message: e.message, taskId });\n  // inspect the failed task record + runLocalCompletionHooks data for root cause\n  await alerting.notifyTaskFailure(taskId, e.message);\n}","preventionTips":["Wrap the task body's fallible I/O (model calls, HTTP) in try/catch with logging.","Validate task inputs before starting the task, not inside it.","Register completion hooks and subscribe to task.failed to capture full error context.","Add retries with backoff around transient upstream calls inside the task body."],"tags":["background-tasks","workflow","task-failure","error-propagation"],"backgroundTag":"task-body-threw","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}