{"record":{"id":"851674ff613decfb","repo":"vercel/ai","slug":"workflow-run-id-not-found-in-x-workflow-run-id-r","errorCode":null,"errorMessage":"Workflow run ID not found in \"x-workflow-run-id\" response header","messagePattern":"Workflow run ID not found in \"x-workflow-run-id\" response header","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/workflow/src/workflow-chat-transport.ts","lineNumber":325,"sourceCode":"    const response = await this.fetch(url, {\n      method: 'POST',\n      body: JSON.stringify(\n        requestConfig?.body ?? { messages, ...options.body },\n      ),\n      headers: requestConfig?.headers,\n      credentials: requestConfig?.credentials,\n      signal: abortSignal,\n    });\n\n    if (!response.ok || !response.body) {\n      throw new Error(\n        `Failed to fetch chat: ${response.status} ${await response.text()}`,\n      );\n    }\n\n    const workflowRunId = response.headers.get('x-workflow-run-id');\n    if (!workflowRunId) {\n      throw new Error(\n        'Workflow run ID not found in \"x-workflow-run-id\" response header',\n      );\n    }\n\n    // Notify the caller that the chat POST request was sent.\n    // This is useful for tracking the chat history on the client\n    // side and allows for inspecting response headers.\n    await this.onChatSendMessage?.(response, options);\n\n    // Flush the initial stream until the end or an error occurs\n    try {\n      const chunkStream = parseJsonEventStream({\n        stream: response.body,\n        schema: uiMessageChunkSchema,\n      });\n      for await (const chunk of createAsyncIterableStream(chunkStream)) {\n        if (!chunk.success) {\n          throw chunk.error;","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/workflow/src/workflow-chat-transport.ts#L307-L343","documentation":"After a successful POST, the chat transport expects the server to return the workflow run ID in the 'x-workflow-run-id' response header. If the header is missing, the client cannot track or reconnect to the workflow run, so it throws.","triggerScenarios":"Server responds 200 but omits the 'x-workflow-run-id' header — e.g. a custom/proxy server implementation, middleware stripping headers, or an outdated server SDK version that doesn't set the header.","commonSituations":"Rolling your own chat endpoint instead of using the workflow server helper; reverse proxy or CORS middleware dropping custom headers; version mismatch between client transport and server package.","solutions":["Ensure the server sets the 'x-workflow-run-id' response header on the chat POST response.","Expose the header through proxies/CORS (e.g. Access-Control-Expose-Headers: x-workflow-run-id).","Update the server workflow package so the header is emitted by the built-in handler."],"exampleFix":"// server (before)\nreturn new Response(stream);\n// after\nreturn new Response(stream, {\n  headers: { 'x-workflow-run-id': workflowRun.id },\n});","handlingStrategy":"validation","validationCode":"const res = await fetch(chatUrl, { method: 'OPTIONS' });\nif (!res.headers.get('access-control-expose-headers')?.includes('x-workflow-run-id')) {\n  console.warn('Server/proxy must expose x-workflow-run-id header');\n}","typeGuard":"function hasWorkflowRunId(headers: Headers): headers is Headers & { get(id: 'x-workflow-run-id'): string } {\n  return headers.get('x-workflow-run-id') !== null;\n}","tryCatchPattern":"try {\n  await transport.sendMessages({ chatId, messages });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('x-workflow-run-id')) {\n    console.error('Server did not return workflow run id header — check server handler version and proxy header exposure');\n  } else throw e;\n}","preventionTips":["Use the official workflow server handler that sets x-workflow-run-id.","Expose custom headers in CORS config (Access-Control-Expose-Headers).","Pin matching versions of client transport and server workflow package.","Integration-test that a chat POST returns the header."],"tags":["http","headers","transport"],"backgroundTag":"missing-response-header","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}