{"record":{"id":"9ba581aa9040b69f","repo":"vercel/ai","slug":"the-response-body-is-empty","errorCode":null,"errorMessage":"The response body is empty.","messagePattern":"The response body is empty\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ai/src/ui/http-chat-transport.ts","lineNumber":265,"sourceCode":"      method: 'GET',\n      headers,\n      credentials,\n      signal: options.abortSignal,\n    });\n\n    // no active stream found, so we do not resume\n    if (response.status === 204) {\n      return null;\n    }\n\n    if (!response.ok) {\n      throw new Error(\n        (await response.text()) ?? 'Failed to fetch the chat response.',\n      );\n    }\n\n    if (!response.body) {\n      throw new Error('The response body is empty.');\n    }\n\n    return this.processResponseStream(response.body);\n  }\n\n  protected abstract processResponseStream(\n    stream: ReadableStream<Uint8Array<ArrayBufferLike>>,\n  ): ReadableStream<UIMessageChunk>;\n}\n","sourceCodeStart":247,"sourceCodeEnd":275,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/ai/src/ui/http-chat-transport.ts#L247-L275","documentation":"In HttpChatTransport.reconnectToStream (packages/ai/src/ui/http-chat-transport.ts:265), the reconnect HTTP response returned a 200-ish status but its body is null. The transport needs a readable stream to feed into processResponseStream, so it throws when `response.body` is falsy. This typically means the server/env stripped or failed to produce the body despite an OK status.","triggerScenarios":"Calling chat reconnect (useChat resume / Chat.reconnectToStream) where the server responds with an OK status code but the fetch Response has `body === null` (e.g. empty-bodied response, opaque responses, or runtimes like some edge environments returning null bodies).","commonSituations":"Custom chat route returning 200 without a stream body; reconnect endpoint implemented incorrectly (returns plain `new Response()` or an empty body); proxy/CDN stripping response bodies; unit-test mocks that build a Response without a body.","solutions":["Fix the server reconnect endpoint so it returns a UI message stream body (e.g. `result.toUIMessageStreamResponse()` from streamText), not an empty 200.","Check for proxies/middleware that may strip or buffer response bodies on the reconnect route.","Verify your fetch mock/polyfill in tests provides a real ReadableStream body.","Wrap reconnect/resume in try-catch and fall back to loading prior messages without streaming when the body is empty."],"exampleFix":"// before (server route)\nreturn new Response(null, { status: 200 });\n// after\nconst result = streamText({ model, messages });\nreturn result.toUIMessageStreamResponse({ originalMessages: messages });","handlingStrategy":"fallback","validationCode":"const res = await fetch(reconnectUrl);\nif (!res.body) {\n  // fall back to loading persisted messages instead of streaming\n}","typeGuard":"function hasResponseBody(res: Response): res is Response & { body: ReadableStream } {\n  return res.body != null;\n}","tryCatchPattern":"try {\n  await chat.reconnectToStream({ chatId });\n} catch (e) {\n  if (e instanceof Error && e.message === 'The response body is empty.') {\n    await loadPersistedMessages(chatId); // fallback path\n  } else throw e;\n}","preventionTips":["Return toUIMessageStreamResponse() from reconnect endpoints so a real stream body is present.","Check proxies/CDNs/middleware for body stripping on streaming routes.","In tests, always construct Response objects with a ReadableStream body.","Guard with `if (!response.body)` before resuming streaming and fall back to message loading."],"tags":["network","streaming","chat-transport","reconnect"],"backgroundTag":"empty-response-body","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}