{"record":{"id":"2f89903d416140b3","repo":"mastra-ai/mastra","slug":"runid-required-to-stream-workflow","errorCode":null,"errorMessage":"runId required to stream workflow","messagePattern":"runId required to stream workflow","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"packages/server/src/server/handlers/workflows.ts","lineNumber":572,"sourceCode":"  responseType: 'stream',\n  pathParamSchema: workflowIdPathParams,\n  queryParamSchema: runIdSchema,\n  bodySchema: streamWorkflowBodySchema,\n  summary: 'Stream workflow execution',\n  description: 'Executes a workflow and streams the results in real-time',\n  tags: ['Workflows'],\n  requiresAuth: true,\n  handler: async ({ mastra, workflowId, runId, resourceId, requestContext, ...params }) => {\n    try {\n      // Use effective resourceId (context key takes precedence over client-provided value)\n      const effectiveResourceId = getEffectiveResourceId(requestContext, resourceId);\n\n      if (!workflowId) {\n        throw new HTTPException(400, { message: 'Workflow ID is required' });\n      }\n\n      if (!runId) {\n        throw new HTTPException(400, { message: 'runId required to stream workflow' });\n      }\n\n      const { workflow } = await listWorkflowsFromSystem({ mastra, workflowId });\n\n      if (!workflow) {\n        throw new HTTPException(404, { message: 'Workflow not found' });\n      }\n\n      const existingRun = await workflow.getWorkflowRunById(runId, { withNestedWorkflows: false });\n\n      if (existingRun && TERMINAL_RUN_STATUSES.includes(existingRun.status)) {\n        throw new HTTPException(409, {\n          message:\n            `Workflow run ${runId} already finished with status \"${existingRun.status}\". ` +\n            `Use /observe to read its stream back, or stream a new runId.`,\n        });\n      }\n","sourceCodeStart":554,"sourceCodeEnd":590,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workflows.ts#L554-L590","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Always call createRun() first and pass its runId to the stream call.","Await createRun before opening the stream to avoid the undefined-runId race.","Check your @mastra/client-js version's stream() signature — pass runId via the expected parameter (body field or path).","Add a falsy guard on runId before dispatching the stream request."],"exampleFix":"// before\nconst runPromise = wf.createRun({});\nconst stream = await wf.stream({ runId: runPromise.runId }); // not awaited -> undefined\n// after\nconst { runId } = await wf.createRun({});\nconst stream = await wf.stream({ runId });","handlingStrategy":"validation","validationCode":"export async function streamWithRun(client: MastraClient, workflowId: string, runId?: string) {\n  const id = runId ?? (await client.getWorkflow(workflowId).createRun({})).runId;\n  if (!id) throw new Error('runId required to stream workflow');\n  return client.getWorkflow(workflowId).stream({ runId: id });\n}","typeGuard":"function hasRunHandle(r: { runId?: string } | undefined): r is { runId: string } {\n  return typeof r?.runId === 'string' && r.runId.length > 0;\n}","tryCatchPattern":"try {\n  const stream = await wf.stream({ runId });\n} catch (e) {\n  if (e instanceof MastraClientError && e.status === 400 && /runid/i.test(e.message)) {\n    const { runId: fresh } = await wf.createRun({});\n    return wf.stream({ runId: fresh });\n  }\n  throw e;\n}","preventionTips":["Always await createRun() before streaming — never pass an unresolved promise's property.","Auto-create a run in your stream helper when runId is absent.","Check the client-js stream() signature for your version to confirm how runId is passed."],"tags":["http-400","validation","missing-parameter","streaming"],"backgroundTag":"missing-required-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}