{"record":{"id":"8047de2944abb3fe","repo":"danny-avila/LibreChat","slug":"failed-to-get-response-reader","errorCode":null,"errorMessage":"Failed to get response reader","messagePattern":"Failed to get response reader","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"client/src/data-provider/Files/sharepoint.ts","lineNumber":58,"sourceCode":"    mutationFn: async ({ file, accessToken, onProgress }) => {\n      const downloadUrl =\n        file.downloadUrl ||\n        `https://graph.microsoft.com/v1.0/drives/${file.driveId}/items/${file.itemId}/content`;\n\n      const response = await fetch(downloadUrl, {\n        headers: {\n          Authorization: `Bearer ${accessToken}`,\n        },\n      });\n\n      if (!response.ok) {\n        throw new Error(`Download failed: ${response.status} ${response.statusText}`);\n      }\n\n      const contentLength = parseInt(response.headers.get('content-length') || '0');\n      const reader = response.body?.getReader();\n      if (!reader) {\n        throw new Error('Failed to get response reader');\n      }\n\n      const chunks: Uint8Array[] = [];\n      let receivedLength = 0;\n\n      while (true) {\n        const { done, value } = await reader.read();\n\n        if (done) break;\n\n        chunks.push(value);\n        receivedLength += value.length;\n\n        if (onProgress) {\n          onProgress({\n            fileId: file.id,\n            fileName: file.name,\n            loaded: receivedLength,","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/client/src/data-provider/Files/sharepoint.ts#L40-L76","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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'`.","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.","Disable or bypass any fetch interceptor / Service Worker that consumes the body before this reader is acquired.","In test environments, mock `response.body.getReader` to return a synthetic reader."],"exampleFix":"// before\nconst reader = response.body?.getReader();\nif (!reader) {\n  throw new Error('Failed to get response reader');\n}\n// after — degrade to blob when streaming is unavailable\nconst reader = response.body?.getReader?.();\nif (!reader) {\n  const blob = await response.blob();\n  return new File([blob], file.name, { type: getMimeTypeFromFileName(file.name) });\n}","handlingStrategy":"fallback","validationCode":"// Detect streaming support before opting into the reader path\nfunction canStreamBody(response: Response): boolean {\n  return typeof response.body?.getReader === 'function';\n}","typeGuard":"function hasReadableBody(response: Response): response is Response & { body: ReadableStream } {\n  return response.body != null && typeof (response.body as any).getReader === 'function';\n}","tryCatchPattern":"let reader = response.body?.getReader?.();\nif (!reader) {\n  // Fallback: consume as a single blob instead of streaming\n  const blob = await response.blob();\n  return new File([blob], file.name, { type: getMimeTypeFromFileName(file.name) });\n}","preventionTips":["Never set `mode: 'no-cors'` on the Graph download fetch — it produces an opaque response with a null body.","Avoid fetch interceptors that consume the body before the reader is acquired.","In jsdom tests, mock response.body.getReader or skip the streaming path."],"tags":["sharepoint","streams","fetch","cors","browser-compat"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}