mastra-ai/mastra · error · MastraNonRetryableError
res.error.message
Error message
res.error.message
What it means
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.
Source
Thrown at packages/core/src/workflows/workflow.ts:2934
...(propagatedForeachOutput ? { foreachOutput: propagatedForeachOutput } : {}),
runId: run.runId,
path: suspendPath,
},
},
{
resumeLabel: Object.keys(res.resumeLabels ?? {}),
},
);
}
}
if (res.status === 'failed') {
const isNonRetryable = Object.values(res.steps).some(stepResult => {
const result = stepResult as StepResult<any, any, any, any>;
return result.status === 'failed' && result.nonRetryable;
});
if (isNonRetryable) {
throw new MastraNonRetryableError(res.error.message, { cause: res.error });
}
throw res.error;
}
if (res.status === 'tripwire') {
const tripwire = res.tripwire;
throw new TripWire(
tripwire?.reason || 'Processor tripwire triggered',
{
retry: tripwire?.retry,
metadata: tripwire?.metadata,
},
tripwire?.processorId,
);
}
return res.status === 'success' ? res.result : undefined;
}View on GitHub (pinned to 75dd419e61)
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.
Example fix
// before
await run.start({ inputData });
// after
const res = await run.start({ inputData });
if (res.status === 'failed') {
console.error('run failed:', res.error, Object.entries(res.steps).filter(([, s]) => s.status === 'failed'));
} Defensive patterns
Strategy: try-catch
Type guard
const isFailedRun = (res: { status: string; error?: unknown; steps?: Record<string, { status: string }> }): boolean =>
res.status === 'failed'; Try / catch
const res = await run.start({ inputData });
if (res.status === 'failed') {
const failing = Object.entries(res.steps ?? {}).filter(([, s]) => s.status === 'failed');
console.error(res.error, failing);
// handle or rethrow
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Unhandled step failure inside a workflow (schema mismatch, tool exception, nested workflow failure); retry budget exhausted; calling code without try/catch around run.start().
Related errors
- ${errorInfo.message}
- Workflow ${workflowId} not found
- Workflow ID is required
- Failed to stream workflow: ${response.statusText}
- Response body is null
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/8dc58c1dc68817c4.
Report an issue: GitHub.