vercel/ai · error
Workflow run ID not found in "x-workflow-run-id" response he
Error message
Workflow run ID not found in "x-workflow-run-id" response header
What it means
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.
Source
Thrown at packages/workflow/src/workflow-chat-transport.ts:325
const response = await this.fetch(url, {
method: 'POST',
body: JSON.stringify(
requestConfig?.body ?? { messages, ...options.body },
),
headers: requestConfig?.headers,
credentials: requestConfig?.credentials,
signal: abortSignal,
});
if (!response.ok || !response.body) {
throw new Error(
`Failed to fetch chat: ${response.status} ${await response.text()}`,
);
}
const workflowRunId = response.headers.get('x-workflow-run-id');
if (!workflowRunId) {
throw new Error(
'Workflow run ID not found in "x-workflow-run-id" response header',
);
}
// Notify the caller that the chat POST request was sent.
// This is useful for tracking the chat history on the client
// side and allows for inspecting response headers.
await this.onChatSendMessage?.(response, options);
// Flush the initial stream until the end or an error occurs
try {
const chunkStream = parseJsonEventStream({
stream: response.body,
schema: uiMessageChunkSchema,
});
for await (const chunk of createAsyncIterableStream(chunkStream)) {
if (!chunk.success) {
throw chunk.error;View on GitHub (pinned to 69428b1f8b)
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.
Example fix
// server (before)
return new Response(stream);
// after
return new Response(stream, {
headers: { 'x-workflow-run-id': workflowRun.id },
}); Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch(chatUrl, { method: 'OPTIONS' });
if (!res.headers.get('access-control-expose-headers')?.includes('x-workflow-run-id')) {
console.warn('Server/proxy must expose x-workflow-run-id header');
} Type guard
function hasWorkflowRunId(headers: Headers): headers is Headers & { get(id: 'x-workflow-run-id'): string } {
return headers.get('x-workflow-run-id') !== null;
} Try / catch
try {
await transport.sendMessages({ chatId, messages });
} catch (e) {
if (e instanceof Error && e.message.includes('x-workflow-run-id')) {
console.error('Server did not return workflow run id header — check server handler version and proxy header exposure');
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to fetch chat: ${response.status} ${await response.te
- Failed to fetch the response.
- The response body is empty.
- ${readErrorMessage({ value, status: response.status })}
- Unknown host tool relay endpoint.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/851674ff613decfb.
Report an issue: GitHub.