{"record":{"id":"6dc3e0a35b9c1491","repo":"danny-avila/LibreChat","slug":"response-status-response-statustext","errorCode":null,"errorMessage":"${response.status} ${response.statusText}","messagePattern":"\\$\\{response\\.status\\} \\$\\{response\\.statusText\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"client/src/data-provider/Files/sharepoint.ts","lineNumber":141,"sourceCode":"      for (let i = 0; i < files.length; i += concurrencyLimit) {\n        chunks.push(files.slice(i, i + concurrencyLimit));\n      }\n\n      for (const chunk of chunks) {\n        const chunkPromises = chunk.map(async (file) => {\n          try {\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(`${response.status} ${response.statusText}`);\n            }\n\n            const blob = await response.blob();\n            const contentType =\n              response.headers.get('content-type') || getMimeTypeFromFileName(file.name);\n\n            const downloadedFile = new File([blob], file.name, {\n              type: contentType,\n              lastModified: Date.now(),\n            });\n\n            completed++;\n            onProgress?.({\n              completed,\n              total: files.length,\n              currentFile: file.name,\n              failed,\n            });","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/client/src/data-provider/Files/sharepoint.ts#L123-L159","documentation":"Thrown inside the batch SharePoint download path when an individual file's Graph content request returns non-2xx. This path is simpler than the single-file path: it calls `response.blob()` directly (no streaming reader) and constructs a `File`. The thrown message is just `${status} ${statusText}` (no `Download failed:` prefix), so it is harder to attribute to a specific item without surrounding context. The failure is collected into the batch's `failed` array rather than aborting the whole batch.","triggerScenarios":"Same Graph failure modes as the single-file case: expired/under-scoped token (401/403), deleted/moved item (404), throttling (429/503). Because it runs per-file inside a batch, one bad item among many produces this error while the others succeed and increment `completed`.","commonSituations":"A multi-file selection where one file's permissions were revoked or it was moved after picking; token expiring mid-batch (large batch takes longer than token TTL); throttling on rapid sequential Graph calls; a stale `downloadUrl` on one item in the batch.","solutions":["Inspect the batch result's `failed` array to see which file(s) failed and their status text.","For token-expiry patterns (first files succeed, later ones 401), refresh the token midway through large batches or reduce batch size.","For 404, instruct the user to re-pick the missing file; for 429/503, retry the failed subset with backoff.","Prefer pre-issued `file.downloadUrl` values when present (they bypass per-item Graph auth) and refresh the picker if they expire."],"exampleFix":"// before\nif (!response.ok) {\n  throw new Error(`${response.status} ${response.statusText}`);\n}\n// after — name the failing item and mark transient failures for retry\nif (!response.ok) {\n  const err = new Error(`Download failed for ${file.name} (${file.itemId}): ${response.status} ${response.statusText}`);\n  err.file = file;\n  err.status = response.status;\n  err.retryable = response.status === 429 || response.status >= 500;\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"// Filter the batch to well-formed files before invoking the mutation\nconst valid = files.filter((f) => f.downloadUrl || (f.driveId && f.itemId));\nif (!valid.length) throw new Error('No valid SharePoint files to download');","typeGuard":"function isSharePointFile(f: unknown): f is SharePointFile {\n  return typeof f === 'object' && f !== null && typeof (f as any).name === 'string';\n}","tryCatchPattern":"// Collect per-file failures rather than aborting the batch\ntry {\n  const response = await fetch(downloadUrl, { headers });\n  if (!response.ok) throw Object.assign(new Error(`${response.status}`), { file, status: response.status });\n} catch (err) {\n  failed.push(err.file?.name ?? 'unknown');\n  continue;\n}","preventionTips":["Refresh the token mid-batch for large sets to avoid mid-run 401s.","Report the failed subset to the user with per-file status for targeted retry.","Rate-limit sequential Graph calls to reduce 429s."],"tags":["sharepoint","microsoft-graph","batch","file-download","network"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}