vercel/ai · error

Failed to fetch chat: ${response.status} ${await response.te

Error message

Failed to fetch chat: ${response.status} ${await response.text()}

What it means

WorkflowChatTransport.sendMessagesIterator performs a POST to the chat endpoint and throws if the HTTP response is not ok or has no body, embedding the status code and response text. It signals that the server rejected the message-send request.

Source

Thrown at packages/workflow/src/workflow-chat-transport.ts:318

          api: this.api,
          trigger,
          messageId,
        })
      : undefined;

    const url = requestConfig?.api ?? this.api;
    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 {

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Check the status code and response text in the error message to identify the server-side cause.
  2. Verify authentication headers/credentials (requestConfig.headers) are sent.
  3. Confirm the chat API endpoint URL and route handler exist and return an SSE/stream body.
  4. Inspect server logs for the corresponding request error.
Defensive patterns

Strategy: try-catch

Validate before calling

// no pre-call check possible for server response; ensure endpoint exists:
// fetch(chatUrl, { method: 'HEAD' }) to verify route availability and auth before POST

Try / catch

try {
  await transport.sendMessages({ chatId, messages });
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Failed to fetch chat:')) {
    const status = parseInt(e.message.match(/\d{3}/)?.[0] ?? '0', 10);
    if (status === 401 || status === 403) fixAuth();
    else if (status >= 500) scheduleRetry();
  } else throw e;
}

Prevention

When it happens

Trigger: POST to the chat API returns a non-2xx status (401 unauthorized, 404 wrong route, 500 server error) or an empty body; network proxy returns an error page; server route not implemented.

Common situations: Missing/misconfigured auth so the server returns 401/403; chat API route path mismatch; server crashed mid-request; CORS or gateway returning 5xx.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/170656cda08754c1. Report an issue: GitHub.