danny-avila/LibreChat · error · Error

Failed to get response reader

Error message

Failed to get response reader

What it means

Thrown when `response.body?.getReader()` returns null/undefined on an otherwise-OK (2xx) Graph download response. `response.body` is the ReadableStream of the fetch; under normal browser conditions on a same-origin or CORS-enabled streaming response it is present. A null body on a 2xx typically indicates an opaque response (CORS `no-cors` mode), a response that was already consumed, or an environment whose fetch implementation does not expose streaming bodies.

Source

Thrown at client/src/data-provider/Files/sharepoint.ts:58

    mutationFn: async ({ file, accessToken, onProgress }) => {
      const downloadUrl =
        file.downloadUrl ||
        `https://graph.microsoft.com/v1.0/drives/${file.driveId}/items/${file.itemId}/content`;

      const response = await fetch(downloadUrl, {
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      });

      if (!response.ok) {
        throw new Error(`Download failed: ${response.status} ${response.statusText}`);
      }

      const contentLength = parseInt(response.headers.get('content-length') || '0');
      const reader = response.body?.getReader();
      if (!reader) {
        throw new Error('Failed to get response reader');
      }

      const chunks: Uint8Array[] = [];
      let receivedLength = 0;

      while (true) {
        const { done, value } = await reader.read();

        if (done) break;

        chunks.push(value);
        receivedLength += value.length;

        if (onProgress) {
          onProgress({
            fileId: file.id,
            fileName: file.name,
            loaded: receivedLength,

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Confirm the fetch is sent in default (cors) mode and that Graph returns the appropriate `Access-Control-Allow-Origin` and streaming headers — avoid `mode: 'no-cors'`.
  2. If streaming progress isn't required, fall back to `await response.blob()` (the batch path at line 141 already does this) instead of reading the stream.
  3. Disable or bypass any fetch interceptor / Service Worker that consumes the body before this reader is acquired.
  4. In test environments, mock `response.body.getReader` to return a synthetic reader.

Example fix

// before
const reader = response.body?.getReader();
if (!reader) {
  throw new Error('Failed to get response reader');
}
// after — degrade to blob when streaming is unavailable
const reader = response.body?.getReader?.();
if (!reader) {
  const blob = await response.blob();
  return new File([blob], file.name, { type: getMimeTypeFromFileName(file.name) });
}
Defensive patterns

Strategy: fallback

Validate before calling

// Detect streaming support before opting into the reader path
function canStreamBody(response: Response): boolean {
  return typeof response.body?.getReader === 'function';
}

Type guard

function hasReadableBody(response: Response): response is Response & { body: ReadableStream } {
  return response.body != null && typeof (response.body as any).getReader === 'function';
}

Try / catch

let reader = response.body?.getReader?.();
if (!reader) {
  // Fallback: consume as a single blob instead of streaming
  const blob = await response.blob();
  return new File([blob], file.name, { type: getMimeTypeFromFileName(file.name) });
}

Prevention

When it happens

Trigger: The fetch was made in `no-cors` mode (response type `opaque`, body null); the body stream was already read by middleware/interceptor before reaching this code; an older/non-standard fetch polyfill; a Service Worker intercepting and returning a Response without a body; in some SSR/headless contexts where streaming isn't backed by a real network body.

Common situations: A global fetch wrapper or axios-style interceptor set `mode: 'no-cors'`; running the download logic in a test (jsdom) where `response.body` is undefined; a Service Worker caching layer returns a synthetic Response; rare browser/WebView versions without ReadableStream support.

Related errors


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/8047de2944abb3fe. Report an issue: GitHub.