{"record":{"id":"8dc58c1dc68817c4","repo":"mastra-ai/mastra","slug":"res-error-message","errorCode":null,"errorMessage":"res.error.message","messagePattern":"res\\.error\\.message","errorType":"exception","errorClass":"MastraNonRetryableError","httpStatus":null,"severity":"error","filePath":"packages/core/src/workflows/workflow.ts","lineNumber":2934,"sourceCode":"              ...(propagatedForeachOutput ? { foreachOutput: propagatedForeachOutput } : {}),\n              runId: run.runId,\n              path: suspendPath,\n            },\n          },\n          {\n            resumeLabel: Object.keys(res.resumeLabels ?? {}),\n          },\n        );\n      }\n    }\n\n    if (res.status === 'failed') {\n      const isNonRetryable = Object.values(res.steps).some(stepResult => {\n        const result = stepResult as StepResult<any, any, any, any>;\n        return result.status === 'failed' && result.nonRetryable;\n      });\n      if (isNonRetryable) {\n        throw new MastraNonRetryableError(res.error.message, { cause: res.error });\n      }\n      throw res.error;\n    }\n\n    if (res.status === 'tripwire') {\n      const tripwire = res.tripwire;\n      throw new TripWire(\n        tripwire?.reason || 'Processor tripwire triggered',\n        {\n          retry: tripwire?.retry,\n          metadata: tripwire?.metadata,\n        },\n        tripwire?.processorId,\n      );\n    }\n\n    return res.status === 'success' ? res.result : undefined;\n  }","sourceCodeStart":2916,"sourceCodeEnd":2952,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workflows/workflow.ts#L2916-L2952","documentation":"After a workflow run finishes with status 'failed', start() rethrows the run's error to the caller. If any failed step was marked nonRetryable, the error is wrapped in MastraNonRetryableError; otherwise the original `res.error` is thrown. The observed message is whatever the underlying run error was.","triggerScenarios":"Awaiting a run (via `run.start()` or watch/unwatch callbacks) whose result status is 'failed'; the thrown value is `res.error` from the failed run — inspect its cause/message for the true failure.","commonSituations":"Unhandled step failure inside a workflow (schema mismatch, tool exception, nested workflow failure); retry budget exhausted; calling code without try/catch around run.start().","solutions":["Inspect `res.error` (or the caught error's cause) to find the failing step and root message.","Catch the error around `await run.start()` and handle per-step failures via `run.steps` status/details.","If the failure is legitimately transient, allow retries (don't mark it nonRetryable) and re-run.","Fix the failing step's logic or input that produced the underlying error."],"exampleFix":"// before\nawait run.start({ inputData });\n// after\nconst res = await run.start({ inputData });\nif (res.status === 'failed') {\n  console.error('run failed:', res.error, Object.entries(res.steps).filter(([, s]) => s.status === 'failed'));\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"const isFailedRun = (res: { status: string; error?: unknown; steps?: Record<string, { status: string }> }): boolean =>\n  res.status === 'failed';","tryCatchPattern":"const res = await run.start({ inputData });\nif (res.status === 'failed') {\n  const failing = Object.entries(res.steps ?? {}).filter(([, s]) => s.status === 'failed');\n  console.error(res.error, failing);\n  // handle or rethrow\n}","preventionTips":["Always inspect res.status before treating a run as successful.","Log per-step results (res.steps) for diagnosis.","Distinguish retryable vs nonRetryable failures when designing steps."],"tags":["workflow","run-failure","error-propagation"],"backgroundTag":"workflow-run-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}