mastra-ai/mastra · warning · HTTPException

runId required to stream workflow

Error message

runId required to stream workflow

What it means

A 400 request-validation error thrown by the workflow stream handler when the `runId` parameter is missing. After workflowId is validated, the handler rejects streaming requests without a runId because the stream is attached to an existing run created via createRun (or starts one only when a runId can be resolved).

Source

Thrown at packages/server/src/server/handlers/workflows.ts:572

  responseType: 'stream',
  pathParamSchema: workflowIdPathParams,
  queryParamSchema: runIdSchema,
  bodySchema: streamWorkflowBodySchema,
  summary: 'Stream workflow execution',
  description: 'Executes a workflow and streams the results in real-time',
  tags: ['Workflows'],
  requiresAuth: true,
  handler: async ({ mastra, workflowId, runId, resourceId, requestContext, ...params }) => {
    try {
      // Use effective resourceId (context key takes precedence over client-provided value)
      const effectiveResourceId = getEffectiveResourceId(requestContext, resourceId);

      if (!workflowId) {
        throw new HTTPException(400, { message: 'Workflow ID is required' });
      }

      if (!runId) {
        throw new HTTPException(400, { message: 'runId required to stream workflow' });
      }

      const { workflow } = await listWorkflowsFromSystem({ mastra, workflowId });

      if (!workflow) {
        throw new HTTPException(404, { message: 'Workflow not found' });
      }

      const existingRun = await workflow.getWorkflowRunById(runId, { withNestedWorkflows: false });

      if (existingRun && TERMINAL_RUN_STATUSES.includes(existingRun.status)) {
        throw new HTTPException(409, {
          message:
            `Workflow run ${runId} already finished with status "${existingRun.status}". ` +
            `Use /observe to read its stream back, or stream a new runId.`,
        });
      }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Always call createRun() first and pass its runId to the stream call.
  2. Await createRun before opening the stream to avoid the undefined-runId race.
  3. Check your @mastra/client-js version's stream() signature — pass runId via the expected parameter (body field or path).
  4. Add a falsy guard on runId before dispatching the stream request.

Example fix

// before
const runPromise = wf.createRun({});
const stream = await wf.stream({ runId: runPromise.runId }); // not awaited -> undefined
// after
const { runId } = await wf.createRun({});
const stream = await wf.stream({ runId });
Defensive patterns

Strategy: validation

Validate before calling

export async function streamWithRun(client: MastraClient, workflowId: string, runId?: string) {
  const id = runId ?? (await client.getWorkflow(workflowId).createRun({})).runId;
  if (!id) throw new Error('runId required to stream workflow');
  return client.getWorkflow(workflowId).stream({ runId: id });
}

Type guard

function hasRunHandle(r: { runId?: string } | undefined): r is { runId: string } {
  return typeof r?.runId === 'string' && r.runId.length > 0;
}

Try / catch

try {
  const stream = await wf.stream({ runId });
} catch (e) {
  if (e instanceof MastraClientError && e.status === 400 && /runid/i.test(e.message)) {
    const { runId: fresh } = await wf.createRun({});
    return wf.stream({ runId: fresh });
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /api/workflows/{workflowId}/stream without runId in path/body, calling `workflow.stream()` without first obtaining a runId, or a race where the stream call fires before createRun resolves.

Common situations: UI starts streaming before createRun's promise resolves (runId still null); custom transport drops the runId body field; SDK version mismatch where stream() no longer auto-creates runs.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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