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.

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.

Appendix: 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)