mastra-ai/mastra · error · HTTPException

runId required to time travel workflow stream

Error message

runId required to time travel workflow stream

What it means

This 400 error is thrown by the time-travel workflow stream handler when the request omits the `runId` path/body parameter. Time traveling a workflow stream requires identifying the specific existing run whose stream should be replayed; without a runId the server cannot locate or recreate the run stream, so it rejects the request before doing any work.

Source

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

  path: '/workflows/:workflowId/time-travel-stream',
  responseType: 'stream',
  pathParamSchema: workflowIdPathParams,
  queryParamSchema: runIdSchema,
  bodySchema: timeTravelBodySchema,
  summary: 'Time travel workflow stream',
  description: 'Time travels a workflow run, starting from a specific step, and streams the results in real-time',
  tags: ['Workflows'],
  requiresAuth: true,
  handler: async ({ mastra, workflowId, runId, requestContext, ...params }) => {
    try {
      const effectiveResourceId = getEffectiveResourceId(requestContext, undefined);

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

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

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

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

      // Validate ownership of existing run before time traveling
      const existingRun = await workflow.getWorkflowRunById(runId);
      if (!existingRun) {
        throw new HTTPException(404, { message: 'Workflow run not found' });
      }
      await validateRunOwnership(existingRun, effectiveResourceId);

      const serverCache = mastra.getServerCache();

      const run = await workflow.createRun({ runId, resourceId: existingRun.resourceId });

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Include the `runId` of the existing workflow run in the request (path or body, matching the route definition).
  2. Fetch the runId first via the workflow runs list endpoint (GET workflow runs) if you don't have it.
  3. Update client SDK code so the runId is passed with the documented parameter name.
  4. Check the server route definition in packages/server/src/server/handlers/workflows.ts to confirm the expected parameter shape.

Example fix

// before
await fetch(`/api/workflows/${workflowId}/stream-v2/time-travel`, { method: 'POST', body: JSON.stringify({ stepId }) });
// after
await fetch(`/api/workflows/${workflowId}/stream-v2/time-travel`, { method: 'POST', body: JSON.stringify({ runId, stepId }) });
Defensive patterns

Strategy: validation

Validate before calling

if (!runId) throw new Error('timeTravel requires a runId obtained from the workflow run');

Type guard

function hasRunId(params: { runId?: string }): params is { runId: string } {
  return typeof params.runId === 'string' && params.runId.length > 0;
}

Try / catch

try {
  await client.getWorkflow(wfId).timeTravel({ runId, stepId, context });
} catch (e) {
  if (e?.status === 400 && /runId required/.test(e?.message ?? '')) {
    throw new Error('Provide the runId of an existing workflow run to time travel');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the time-travel workflow stream endpoint (e.g. POST /api/workflows/:workflowId/stream-v2/time-travel or equivalent) without providing `runId`, or providing it under a wrong key so the handler destructures it as undefined.

Common situations: Client SDK calls built by hand that forget the runId field; frontend code that navigates to time-travel before a runId has been selected; API route changes between server versions where the parameter moved from query string to body.

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/e9a6f514a555b8cc. Report an issue: GitHub.