mastra-ai/mastra · error

${metadata?.errorMessage || 'Workflow execution failed'}

Error message

${metadata?.errorMessage || 'Workflow execution failed'}

What it means

useStreamWorkflow's observer throws this when the workflow stream reports status 'failed'. The metadata payload of the failure event may carry an errorMessage, which is used as the message; otherwise the generic 'Workflow execution failed' is used. It converts an async stream termination state into a thrown error so React consumers (and React Query-style error handling) see it as a failure.

Source

Thrown at client-sdks/react/src/workflows/use-stream-workflow.ts:115

        return;
      }
      const error = err instanceof Error ? err : new Error(defaultMessage);
      onError?.(error, defaultMessage);
      setStreamingState?.(false);
    },
    [onError],
  );

  const handleWorkflowFinish = useCallback((value: StreamVNextChunkType) => {
    if (value.type === 'workflow-finish') {
      const streamStatus = value.payload?.workflowStatus;
      const metadata = value.payload?.metadata;
      setStreamResult(prev => ({
        ...prev,
        status: streamStatus,
      }));
      if (streamStatus === 'failed') {
        throw new Error(metadata?.errorMessage || 'Workflow execution failed');
      }
      // Tripwire status is not an error - it's handled separately in the UI
      // Don't throw an error for tripwire status
    }
  }, []);

  const streamWorkflow = useMutation<void, Error, StreamWorkflowParams>(
    async ({ workflowId, runId, inputData, initialState, requestContext: playgroundRequestContext, perStep }) => {
      // Clean up any existing reader before starting new stream
      if (readerRef.current) {
        readerRef.current.releaseLock();
      }

      if (!isMountedRef.current) return;

      setIsStreaming(true);
      setStreamResult({ input: inputData } as WorkflowStreamResult);
      const workflow = client.getWorkflow(workflowId);

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Read metadata.errorMessage / the thrown message to find the failing step, then fix the bug in the workflow step
  2. Inspect the workflow run's trace/logs in Mastra Studio for the root cause
  3. Wrap your usage of the hook's stream in error handling and surface retry/resume UX
  4. Check that resume/timeTravel is only called on runs in a compatible state

Example fix

// before
const { streamResult } = useStreamWorkflow({ workflowId }); // error surfaces unhandled
// after
useEffect(() => {
  if (error) console.error('Workflow failed:', error.message); // show retry UI
}, [error]);
Defensive patterns

Strategy: try-catch

Validate before calling

// check workflow run status before/after streaming
if (streamResult?.status === 'failed') {
  console.error('Workflow failed:', streamResult?.metadata?.errorMessage);
}

Type guard

function isFailedEvent(value: unknown): value is { type: 'workflow-update'; payload: { metadata?: { errorMessage?: string } } } {
  return typeof value === 'object' && value !== null && (value as any).type === 'workflow-update';
}

Try / catch

try {
  await observeWorkflowStream();
} catch (err) {
  if (err instanceof Error && /Workflow execution failed/.test(err.message)) {
    showError(err.message); // offer resume/retry
  } else throw err;
}

Prevention

When it happens

Trigger: Streaming a workflow whose run transitions to status 'failed' — e.g. a step threw, the workflow's error handler re-threw, or the engine aborted the run. Observed inside the stream-value observer in useStreamWorkflow.

Common situations: A workflow step raised an unhandled exception; input schema validation failed server-side; resume/timeTravel hit a broken run; transient storage or network failure during the run.

Related errors


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